我有一个活跃使用的应用程序,很少发生UI线程的“冻结”。这当然会导致应用程序无响应,并要求用户手动终止它。
由于这个问题的复制有多么困难,我想开发一些工具来帮助收集有关何时在现场发生的数据以及当时正在发生的事情。我正在考虑的是某种背景监视任务,它将监视来自周期性调度的UI线程任务的“心跳”。如果它变得安静太长时间,我可以说UI被有效锁定(或者至少停滞的时间超过了我想要的时间)并因此收集数据。
所以,为此做准备,有几个问题:
这样的事情已经存在吗?这似乎是一个相当普遍的问题,所以如果有现有的工具可以帮助诊断这个问题,那么使用这些工具可能是值得的,而不是滚动我自己的解决方案。
我还在讨论在检测到冻结时我应该尝试收集哪些信息。有没有办法让我轻松抓取UI线程的堆栈跟踪,以便记录它?可能从所有活动线程中获取堆栈跟踪?有什么方法可以捕获完整的调试转储吗?
答案 0 :(得分:3)
这样的事情已经存在吗?
是。必须在进程的外部执行此操作,因为死锁状态使得诊断代码很可能也会出现死锁。 DebugDiag utility明确支持挂起的应用。
我还在辩论我应该尝试收集哪些信息
你从DebugDiag中获取的minidump应该足以让你有机会诊断原因。演示解决死锁的示例调试会话是shown here。
当然,很难看好你的代码永远不会伤害。 UI线程死锁通常由以下原因引起:
在工作线程上显示一个窗口。执行此操作时,SystemEvents类是一个非常重要的麻烦制造者。它需要在UI线程上触发它的事件,但这需要它猜测程序中哪个特定线程实际上是UI线程。一旦它猜错了,你就会被设置为一个自发的死锁任何时间。请注意,这不需要您在自己的代码中使用SystemEvents类,许多控件订阅ThemeChanged事件以重新绘制自己。 Fwiw,我链接的调试会话演示了这样的僵局。注意自制的启动画面,在工作线程而不是UI线程上创建的“进度”窗口,当然还有任何显示UI的工作线程。
数据绑定控件,其底层绑定源在工作线程上更新。当然很常见,因为dbase查询往往很慢。此类控件必须首先明确禁止。