所以,我现在已经得到了这个错误,我进行了一些测试,但我无法弄清楚问题。调用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");
}
}
答案 0 :(得分:2)
当计时器调用EndTimer_Elapsed
方法时,您不在拥有锁的同一个线程中,因此不允许在那里释放锁。
这是一个很好的例子,说明为什么人们应该完全避免使用Monitor.Enter/Exit
。即使是并发编程方面的专家也能让一切都做得恰到好处,这对任何其他人来说都是一个雷区,这一点非常棘手。如果您坚持使用lock
语句使用Monitor,那么犯这种错误会变得更加困难。 :)
最后请注意,您的示例为什么使用此锁定并不是很清楚。您可以考虑发布一个不同的问题来解释您尝试解决的同步问题,以便您可以在没有Monitor.Enter/Exit