我有一段非常简单的代码,很少抛出“System.ApplicationException:对象同步方法是从未同步的代码块中调用的。”调用 ReleaseMutex ()时。

我从逻辑上分析了该方法的流程,只是无法理解这种情况的发生方式/原因。
据我了解,在这种情况下,互斥体的所有权得到保证:

    readonly string mutexKey;

    public Logger(string dbServer, string dbName)
    {
        this.mutexKey = ServiceManagerHelper.GetServiceName(dbServer, dbName);
    }

    private void Log(LogType type, string message, Exception ex)
    {
        using (var mutex = new Mutex(false, mutexKey))
        {
            bool acquiredMutex;
            try
            {
                acquiredMutex = mutex.WaitOne(TimeSpan.FromSeconds(5));
            }
            catch (AbandonedMutexException)
            {
                acquiredMutex = true;
            }

            if (acquiredMutex)
            {
                try
                {

                    // some application code here

                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
        }
    }

最佳答案

        catch (AbandonedMutexException)
        {
            acquiredMutex = true;
        }

这是代码中非常严重的错误。捕获AbandonedMutexException永远是不正确的,它是非常严重的不幸事故。另一个线程获取了互斥锁,但是在不调用ReleaseMutex()的情况下终止了。您无法恢复丢失的同步,并且互斥锁不再可用。

您确实很幸运,因为犯了一个错误并假设您无论如何都获得了互斥量。你没有现在,ReleaseMutex()调用将轰炸,并带有您引用的异常。

除了终止程序(明智的选择)或完全禁用日志记录之外,您无法从此灾难中恢复,因此互斥量将不再使用。通过删除catch子句来做出明智的选择。发现问题的真正根源是,崩溃了且未调用ReleaseMutex()的线程不在此问题的讨论范围之内,没有任何提示。您一直在忽略这个问题,而是通过捕获AME来解决它,您不能忽略它。

10-04 12:56