Monitor.Exit抛出SynchronizationLockException

时间:2014-10-22 22:29:04

标签: c# multithreading exception thread-safety monitor

所以,我现在已经得到了这个错误,我进行了一些测试,但我无法弄清楚问题。调用Monitor.Exit()时出现System.Threading.SynchronizationException。首先,我为我使用的所有Monitor方法创建了一个包装器,它将“Locked”和“Unlocked”打印到屏幕上。在打电话给Exit之前,这打印得很好,它说锁是锁定的。当我调用exit时它会抛出错误而FAILS会解锁我的对象。从我的UI中可以看出这一点。它说无法从非同步块中执行某些操作?

注意:My Monitor.Exit命令在与我的Monitor.Enter命令不同的方法调用中调用。它仍然是安全的,但这可能是问题吗?

编辑:背景信息:我正在实施类似马里奥的游戏。当Mario进入Transition时,我的团队希望我们所有的各种计时器都停止更新(阻止他们的线程)并只对我们的播放器进行特定的更新。所有Timer线程都有一个名为TimerLock的公共锁。以下是此转换的示例代码。

    public void Begin()
    {
        if (Monitor.TryEnter(ManagedTimer.Lock,100))
        {

            try
            {
                //Turn off updating for all objects
                TurnOffPhysicsUpdate(); //Psuedocode for this...

                //Create timer till end event
                EndTimer = new System.Timers.Timer(600.00);
                EndTimer.AutoReset = false;
                EndTimer.Elapsed += EndTimer_Elapsed;
                EndTimer.Enabled = true;
                EndTimer.Start();

                //Create swap timer
                SwapTimer = new System.Timers.Timer(25.0);
                SwapTimer.AutoReset = false;
                SwapTimer.Elapsed += SwapTimer_Elapsed;
                SwapTimer.Enabled = true;
                SwapTimer.Start();
            }
            catch (Exception e)
            {
                EndFreeze();
                Debug.WriteLine("Failed to setup transition: " + e.Message);
            }
        }
    }

    private void SwapTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
            SwapTimer.Stop();
            //Transition Mario State....
            SwapTimer.Start();
    }

    private void EndTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        EndFreeze();
    }

    private void EndFreeze()
    {
        try
        {
            SwapTimer.Stop();
            EndTimer.Stop();

            TurnOnPhysicsUpdate(); //psuedocode

            //Ensure Mario ends in the proper state
            user.StateMachine.TransitionSizeState(newState);
        }
        catch (Exception e)
        {
            Debug.WriteLine("FATAL ERROR: " + e.Message);
        }
        finally
        {
            //Exception occurs here!!!!!!!!!!!!!
            Monitor.Exit(ManagedTimer.Lock,"TimerLock");
        }
    }

1 个答案:

答案 0 :(得分:2)

当计时器调用EndTimer_Elapsed方法时,您不在拥有锁的同一个线程中,因此不允许在那里释放锁。

这是一个很好的例子,说明为什么人们应该完全避免使用Monitor.Enter/Exit。即使是并发编程方面的专家也能让一切都做得恰到好处,这对任何其他人来说都是一个雷区,这一点非常棘手。如果您坚持使用lock语句使用Monitor,那么犯这种错误会变得更加困难。 :)

最后请注意,您的示例为什么使用此锁定并不是很清楚。您可以考虑发布一个不同的问题来解释您尝试解决的同步问题,以便您可以在没有Monitor.Enter/Exit

的情况下正确设计代码