我使用Monitor类来管理临界区。但有时我会遇到SynchronizationLockException
,并显示以下消息
An unhandled exception of type 'System.Threading.SynchronizationLockException' occurred in ManagedType.dll
Additional information: Object synchronization method was called from an unsynchronized block of code.
我的代码如下
Object^ lockObj = gcnew Object(); //Global variable
bool GetValue()
{
try
{
Monitor::Enter(lockObj);
return this.value;
}
finally
{
Monitor::Exit(lockObj);
}
}
Monitor::Exit(lockObj)
调用时引发的SynchronizationLockException
。
我已经在这个论坛和互联网上搜索过了,但大多数话题包括MSDN都说“当你试图在Monitor.Enter()和Monitor.Exit()中使用值类型变量而不是引用类型时,会抛出这个异常”。
但在我的例子中,我使用的是lockObj,它是引用对象。所以我不知道为什么它会抛出这个异常。有人能帮我吗?
非常感谢,
T&T组!
发布于 2013-06-14 23:19:34
发布的代码根本就是错误的。::Enter()调用必须出现在{}块的外部。
故障模式非常糟糕且无法诊断。如果Enter()调用出于任何原因抛出异常,那么finally{}块中的Exit()调用将崩溃,并记录异常,因为从未进入监视器。它是不可诊断的,因为该异常替换了Enter()方法抛出的异常,您既看不到它,也捕捉不到原始异常。所以你不知道为什么这段代码会失败,也不能修复这个问题。
将Enter调用移到try块的上方。这仍然不能解决你的代码崩溃的问题,但至少你现在有了一些关于真正出错的信息。
顺便说一句,请注意.NET 4.0中添加的Monitor::Enter()重载,旨在解决此类问题。它需要一个额外的bool%参数,当Enter()成功时,该参数将被设置为true,这样您就知道调用Exit()是安全的。
发布于 2013-06-14 23:37:22
@Hans是部分正确的。使用接受引用布尔值的Monitor.Enter重载。此重载始终设置传递给ref参数lockTaken的变量的值,即使该方法抛出异常,因此该变量的值是测试是否必须释放锁的可靠方法。但是一定要把Monitor.Enter调用放在try块中。您的代码应该类似于
bool acquiredLock = false;
try
{
Monitor.Enter(lockObject, ref acquiredLock);
// Code that accesses resources that are protected by the lock.
}
finally
{
if (acquiredLock)
{
Monitor.Exit(lockObject);
}
}
发布于 2015-04-18 04:18:40
好了,我刚刚处理了这个问题。我相信这会解决你的问题。尝试将对象设置为NULL;它对我有效。
Object^ lockObj=NULL;
Monitor::Enter(lockObj);
try
{
return this.value;
}
finally
{
Monitor::Exit(lockObj);
}
https://stackoverflow.com/questions/17110673
复制相似问题