Monitor.Exit()上的SynchronizationLockException?

时间:2013-06-14 14:19:42

标签: visual-studio c++-cli managed

我正在使用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);
    }
}

调用SynchronizationLockException时抛出的Monitor::Exit(lockObj)

我在这个论坛和互联网上搜索过,但大多数主题包括MSDN都说“当你尝试在Monitor.Enter()和Monitor.Exit中使用值类型变量而不是引用类型时,会抛出此异常( )”。

但在我的情况下,我使用的是作为引用对象的lockObj。所以我不知道它为什么会抛出这个异常。有人可以帮帮我吗?

非常感谢,

T&安培; T组

3 个答案:

答案 0 :(得分:4)

发布的代码根本就是错误的。 Monitor :: Enter()调用必须出现在try {}块之外。

失败模式是令人讨厌且无法确定的。如果Enter()调用为任何原因抛出异常,则finally {}块中的Exit()调用将因记录的异常而崩溃,因为从未输入监视器。它是不可诊断的,因为异常替换了由Enter()方法抛出的异常,您无法看到它也无法捕获原始异常。所以你不知道为什么这个代码失败了,无法解决问题。

将Enter调用移到try块上方。这仍然无法解决您的代码崩溃的问题,但至少您现在可以获得一些关于真正出错的正确信息。

顺便说一句,请注意.NET 4.0中添加的Monitor :: Enter()重载,旨在解决此类问题。它需要一个额外的bool%参数,当Enter()成功时将设置为true,因此您知道调用Exit()是安全的。

答案 1 :(得分:3)

@Hans部分正确。使用带有ref bool的Monitor.Enter重载。 此重载始终设置传递给ref参数lockTaken的变量的值,即使该方法抛出异常,因此变量的值是测试是否必须释放锁的可靠方法。 但是请在try块内保留Monitor.Enter调用。 您的代码应该类似于

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);
    }
}

答案 2 :(得分:-1)

好的,我刚刚处理过这个问题。我相信这会解决你的问题。尝试将对象设置为NULL;它对我有用。

Object^ lockObj=NULL;

Monitor::Enter(lockObj);
try
{
     return this.value;
}
 finally
 {
     Monitor::Exit(lockObj);
 }