【问题标题】:Error while using Monitor class in WinForms. Object synchronization method was called from an unsynchronized block of code在 WinForms 中使用 Monitor 类时出错。从未同步的代码块调用对象同步方法
【发布时间】:2016-06-12 11:47:27
【问题描述】:

使用 System.Threading 的 Win Form 应用程序。两个线程 threadA 和 threadB 使用相同的方法 sumNumber 启动。 sumNumber 更新变量total。所以这两个线程尝试更新同一个变量。

使用监控类同步访问total变量。

在 WindowsFormsApplication2.exe 中出现“类型为 'System.Threading.SynchronizationLockException' 的未处理异常”的运行时异常

附加信息:对象同步方法是从未同步的代码块调用的

我该如何正确使用这个中的 Monitor 类。

 int total;

 private void button3_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            total = 0;

            Thread threadA;
            Thread threadB;

            threadA = new Thread(sumNumber);
            threadA.Start();
            threadB = new Thread(sumNumber);
            threadB.Start();

            threadA.Join();
            threadB.Join();

            listBox1.Items.Add("Total is: " + total);
        }

        public void sumNumber()
        { 
            long numRepeats = 100000;

            for (int i = 0; i < numRepeats; i++)
            {
                Monitor.Enter(total);
                total = total + 10;
                Monitor.Exit(total);
            }

        }

【问题讨论】:

    标签: c# multithreading winforms


    【解决方案1】:

    您传递给 Monitor.Enter 和 Monitor.Exit 的对象必须相同。由于 total 的值发生了变化,Monitor.Exit 尝试退出,但是没有任何对应的 Monitor.Enter 具有相同的对象,从而抛出异常

    你应该有

    private readonly object TotalLock = new object();

    作为成员变量,那么

    Monitor.Enter(TotalLock);
    total = total + 10;
    Monitor.Exit(TotalLock);
    

    可以简写为

    lock (TotalLock)
    {
        total = total + 10;
    }
    

    【讨论】:

    • 所以 Monitor 对象只能用于引用类型,不能用于原始数据类型。
    • 方法签名是public static void Enter(object obj),所以如果你传入一个值类型,它会被装箱,一切都会中断
    猜你喜欢
    • 2011-11-28
    • 2012-09-14
    • 1970-01-01
    • 2015-02-06
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    相关资源
    最近更新 更多