ReleaseMutex:从非同步代码块调用对象同步方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReleaseMutex:从非同步代码块调用对象同步方法相关的知识,希望对你有一定的参考价值。

我有这个相当简单的代码片段很少抛出“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来掩盖它,你不能忽视它。

另一答案

从不具有互斥锁的线程调用ReleaseMutex()时会引发此异常。在// some application code here中搜索释放互斥锁的代码。

还要重新考虑你是否真的从你调用ReleaseMutex()的同一个线程中调用WaitOne()。示例:我到达此帖子是因为我使用async/await并且我的代码在另一个线程上恢复并尝试释放线程不拥有的互斥锁。

以上是关于ReleaseMutex:从非同步代码块调用对象同步方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 Mutex 同步 C# 对象:在 C# 对象析构函数中调用 ReleaseMutex() 时出现问题

SynchronizationLockException(对象同步方法是从未同步的代码块中调用的。)释放锁时

对象同步方法是从未同步的代码块中调用的。 Mutex.Release() 上的异常

java的同步方法和同步代码块,对象锁,类锁区别

多线程基础

synchronized将任意对象作为对象监视器