首页 > 解决方案 > 使用 Monitor.Exit 引发的异常

问题描述

我似乎无法弄清楚为什么我会得到这个例外。这是我正在运行的代码和我尝试过的事情。

public static Boolean IsRunning = false;

public static void Process()
{
    Boolean lockTaken = false;
    try
    {
        Monitor.TryEnter(IsRunning, ref lockTaken);
        if (lockTaken)
        {
            // Run code
        }
    }
    catch (Exception e) { e.Log(); }
    finally
    {
        if (lockTaken)
        {
            Monitor.Exit(IsRunning);
        }
    }
}

出于某种原因,我在该Monitor.Exit(IsRunning);行引发了异常,这很奇怪,因为如果监视器成功获得对象的锁定,我只运行该行代码IsRunning。任何可能导致抛出此异常的线索?

抛出的异常是从未同步的代码块调用对象同步方法。

标签: c#clr

解决方案


嗯...属性IsRunning的类型System.Boolean是值类型或结构。您只能在引用类型的实例上设置锁定。

在这里您可以阅读有关Monitor课程的信息:https ://docs.microsoft.com/en-us/dotnet/api/system.threading.monitor?view=netcore-3.1

在这里您可以阅读有关值和引用类型的信息:https ://www.tutorialsteacher.com/csharp/csharp-value-type-and-reference-type

当您将值类型的实例作为 aSystem.Object或通过接口传递给方法时,就会发生装箱分配。

它是什么?

CLR 分配内存,然后将传递的实例的值复制到堆中,并将对分配对象的引用真正传递给被调用的方法。因此,当您调用EnterCLR 时,它会分配一个新对象并将它的引用传递给该方法。当您调用Exit它时,它会再分配一个新对象,并且它是另一个对象。所以当前线程没有锁定它。这就是引发异常的原因。

您可以在此处阅读有关装箱和拆箱的信息:https ://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing#:~:text=Boxing%20is%20the% 20 进程%20 的值%20 类型%20 来自%20%20 对象


推荐阅读