从委托中锁定静态对象不起作用
为什么这不起作用?
private static object Lock_HandleError = new object(); public static void HandleError(Exception ex) { lock( Lock_HandleError ) { //IF the UI is processing a visual tree event (such as IsVisibleChanged), it throws an exception when showing a MessageBox as described here: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/44962927-006e-4629-9aa3-100357861442 //The solution is to dispatch and queue the MessageBox. We must use BeginInvoke because dispatcher processing is suspended in such cases. Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate() { lock( Lock_HandleError ) { Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate(){ HandleError(new Exception("testing purposes only")); }, DispatcherPriority.Background); MessageBox.Show(ex.Message, "Application Error", MessageBoxButton.OK, MessageBoxImage.Error); //This point is not reached until the user clicks "OK" } }, DispatcherPriority.Background); } } public void main() { HandleError(new Exception("The first error")); }
上述代码的预期行为是一次出现一条错误消息,当用户单击“确定”时, Lock_HandleError
对象将从调度的线程中释放,并且下一次调用HandleError可以继续 – 但是我得到的是无限级联的错误消息,而没有达到“OK”。
为什么这个锁没有工作?
通过在每个lock语句的入口和出口处设置断点,我可以清楚地看到委托正在调用lock()
并再次调用新的“HandleError”调用,然后在MessageBox上暂停以等待用户输入。
同时,在另一个线程中,调度HandleError的调用会运行 – 但不是像它应该那样等待lock()语句,它只是爆破它,即使MessageBox委托明确放置了一个锁并且还没有释放它。
两部分答案:
-
了解锁是可重入的。 当一个线程已经锁定一个对象时,该线程可以一次又一次地使用相同的锁而不会阻塞。
-
当第一个MessageBox启动时,UI线程仍在处理消息,因此在UI线程上处理对
HandleError
后续(递归)调用(因为它已经持有锁,可以重新输入它)。
为什么这个锁没有工作?
允许线程输入它已拥有的锁定语句。 在essense中,lock不会阻塞自己的线程。
因此,正在发生的事情是原始线程获取锁定,然后允许将消息添加到Dispatcher的队列中。 它可以添加任意多个。
Dispatcher在处理时获取第一条消息,然后调用HandleError。 由于它在调度程序线程中运行,因此允许它进入外部和内部锁定,并再次调用HandleError,以无限循环递归地向队列添加新消息。
- 检查特定网站上的大代理列表的最快方法是什么?
- 是否可以从另一个表单触发click事件?
- DirectoryInfo.EnumerateFiles(…)导致UnauthorizedAccessException(和其他exception)
- 是否可以在.NET 4.0框架上使用TLS1.2发送HttpWebRequest
- 使用Rx确定鼠标拖动结束的正确方法是什么?
- 使用ASP.NET Web API并排进行基本和表单身份validation
- 使用嵌套的Parallel.For
- GetSystemMetrics()为.NET 4.5和.NET 4.0返回不同的结果
- WCF messageheader与messagebodymember?