我有这个非常简单的代码,很少抛出“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();
}
}
}
}
答案 0 :(得分:6)
catch (AbandonedMutexException)
{
acquiredMutex = true;
}
这是您代码中的一个非常严重的错误。捕获AbandonedMutexException永远不正确,这是一个非常严重的事故。另一个线程获得了互斥锁,但在没有调用ReleaseMutex()的情况下终止了。您已无法恢复同步,并且互斥锁不再可用。
你犯了一个错误并且假设你无论如何都获得了互斥锁,这有点幸运。你没有。现在,ReleaseMutex()调用将以您引用的异常进行轰炸。
除了通过终止程序(明智的选择)或完全禁用日志记录之外,您无法从此次事故中恢复,因此永远不会再次使用互斥锁。通过删除catch子句做出明智的选择。发现问题的真正根源,那个崩溃并且没有调用ReleaseMutex()的线程,对于这个问题已经脱离了上下文,没有任何提示。你一直忽略了这个问题,通过捕捉AME来掩盖它,你不能忽视它。
答案 1 :(得分:0)
当您从不拥有互斥锁的线程中调用ReleaseMutex()
时,会引发此异常。在// some application code here
中搜索释放互斥量的代码。
还要重新考虑您实际上是否从调用ReleaseMutex()
的同一线程中调用WaitOne()
。示例:我到达此帖子是因为我正在使用async/await
,并且我的代码在另一个线程上恢复,并试图释放该线程不拥有的互斥锁。
答案 2 :(得分:0)
就我而言,我看到的行为与内森·舒伯克格尔(Nathan Schubkegel)相同。我使用await
,Thread.CurrentThread.ManagedThreadId
为“相同”线程提供了另一个值。我的意思是,线程以ManagedThreadId == 10
开始,并且Mutex
拥有此线程ID,但后来ReleaseMutex()
导致ApplicationException
并显示以下消息:“对象同步方法是从不同步的代码块”,此时我看到ManagedThreadId == 11
:)。看来,await
有时会在返回时更改线程ID。看来,这就是原因。 Mutex
认为另一个线程想要释放它。令人遗憾的是,Mutex
文档目前没有达到 ATTENTION 。