如何找出线程锁定的位置?

时间:2010-06-11 21:25:17

标签: .net winforms thread-safety

我们公司的一个Windows窗体应用程序在几个月内出现了一个奇怪的问题。 该应用程序对我们的大多数客户非常可靠,但在一些PC(主要是无线局域网连接)上,应用程序有时只是没有响应。 (您单击UI并且窗口会要求您等待或终止该应用程序。)

我无法长时间追踪这个问题,但现在我想出了发生了什么。 该应用程序有这行代码

// don't blame me for this. Wasn't my code :D
Control.CheckForIllegalCrossThreadCalls = false

并使用一些后台线程来修改控件。

没有我找到一种方法来重现应用程序停止响应我的开发机器上的错误并将其跟踪到我实际上使用Invoke()在主线程中运行任务的行。

Me.Invoke(MyDelegate, arg1, arg2)

显然在某处有线程锁定。 删除后

Control.CheckForIllegalCrossThreadCalls = false

声明并重构整个程序以使用Invoke()如果从后台线程修改控件,问题(希望)已经消失。

但是,我想知道是否有办法在没有调试每行代码的情况下找到这样的错误(即使我在应用程序停止响应后进入调试器我也无法分辨最后发生的事情,因为IDE没有跳转到Invoke()语句)

换句话说:

  

如果我的应用程序挂起,我怎么能弄清楚   哪一行代码已被执行   持续多久?

甚至可能在客户PC上。

我知道VS2010提供了一些向后调试功能,也许这将是一个解决方案,但目前我正在使用VS2008。

3 个答案:

答案 0 :(得分:2)

也许这可能会对您有所帮助:http://www.debuginspector.com/index.htm

它是一个Visual Studio扩展,允许您跟踪死锁,它还有一些其他漂亮的功能可用于调试线程(例如查看多个线程的调用堆栈而无需进入线程窗口)。

答案 1 :(得分:1)

答案 2 :(得分:1)

您很可能正确识别出罪魁祸首,将CheckForIllegalCrossThreadCalls设置为false是创建随机死锁的好方法。该属性存在的唯一原因是允许调试borked .NET 1.x程序。

要解决死锁问题,您需要使用Debug + Windows + Threads窗口在各个线程之间切换并查看其调用堆栈。但考虑到源的可能性,这将是困难的,因为很可能非托管代码对消息队列或SendMessage()执行某些操作。您没有编写的代码,也没有源代码或调试符号。它们也往往是随机的,下一次死锁可能看起来完全不同。

Windows基本上是线程不安全的对象。他们有很多与之相关的国家。不仅在Windows窗体类包装器中,在Windows本身内部也是如此。我相信你解决了这个问题。