Monitor.Exit throws SynchronizationLockException

本文关键字:SynchronizationLockException throws Exit Monitor | 更新日期: 2023-09-27 18:27:33

所以,我已经收到这个错误一段时间了,我进行了一些测试,但我无法解决问题。在调用Monitor.Exit()时,我得到了System.Threading.SynchronizationException。首先,我为我使用的所有Monitor方法创建了一个包装,将"Locked"answers"Unlocked"打印到屏幕上。这打印出来很好,就在我呼叫Exit之前,它说锁被锁住了。当我调用exit时,它抛出错误并未能解锁我的对象。这在我的UI中是显而易见的。它说了一些关于不能从非同步块执行的内容?

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

编辑:背景信息:我正在实施一个类似马里奥的游戏。当马里奥进入过渡时,我的团队希望我们所有的计时器停止更新(阻止他们的线程),只对我们的玩家进行特定的更新。所有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");
        }
    }

Monitor.Exit throws SynchronizationLockException

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

这是一个很好的例子,说明了为什么应该完全避免使用Monitor.Enter/Exit。即使是并行编程专家也很难把一切都做好,这对其他人来说都是一个雷区。如果您坚持通过lock语句使用Monitor,则会更难犯这种错误。:)

最后请注意,从您的示例中还不清楚您为什么使用此锁。您可以考虑发布一个不同的问题来解释您试图解决的同步问题,这样您就可以在没有Monitor.Enter/Exit 的情况下正确设计代码。