【问题标题】:Detecting stalled UI thread检测停滞的 UI 线程
【发布时间】:2014-02-07 15:33:54
【问题描述】:

我有一个正在积极使用的应用程序,UI 线程很少发生“冻结”。这当然会导致应用程序变得无响应并需要用户手动终止它。

由于重现此问题非常困难,我想开发一些工具来帮助收集有关该问题何时在现场发生以及当时发生的情况的数据。我正在考虑的是某种后台看门狗任务,它将监视来自定期调度的 UI 线程任务的“心跳”。如果它安静太久,我可以说 UI 被有效地锁定(或者至少停滞的时间比我想要的要长得多),因此收集数据。

所以,为了准备这个,有几个问题:

  1. 这样的东西已经存在了吗?这似乎是一个相当普遍的问题,所以如果有现有的工具可以帮助诊断这个问题,那么使用这些工具而不是推出我自己的解决方案可能是值得的。

  2. 我仍在争论当检测到冻结时我应该尝试收集哪些信息。有什么方法可以让我轻松获取 UI 线程的堆栈跟踪以便记录它吗?可能从所有活动线程中获取堆栈跟踪?有什么方法可以捕获完整的调试转储吗?

【问题讨论】:

    标签: c# .net multithreading locking


    【解决方案1】:

    这样的东西已经存在了吗?

    是的。必须在进程之外执行此操作,因为一个死锁的进程很可能导致诊断代码也将死锁。 DebugDiag utility 明确支持挂起的应用程序。

    我仍在争论我应该尝试收集哪些信息

    您从 DebugDiag 中获得的小型转储应该足以让您有机会诊断原因。演示解决死锁的示例调试会话是 shown here

    当然,仔细检查您的代码也不会有什么坏处。 UI 线程死锁通常由以下原因引起:

    • 在工作线程上显示一个窗口。执行此操作时,SystemEvents 类是一个非常重要的麻烦制造者。它需要在 UI 线程上触发其事件,但这需要它猜测程序中的哪个特定线程实际上是 UI 线程。一旦它猜错了,你就会在以后任何时间陷入自发的死锁。请注意,这不需要您在自己的代码中使用 SystemEvents 类,许多控件订阅 ThemeChanged 事件以重新绘制自己。 Fwiw,我链接到的那个调试会话演示了这样一个死锁。当心自制启动画面、在工作线程而不是 UI 线程上创建的“进度”窗口,当然还有任何显示 UI 的工作线程。

    • 其底层绑定源在工作线程上更新的数据绑定控件。当然很常见,因为 dbase 查询往往很慢。此类控件必须首先明确解除绑定。

    【讨论】:

    • 谢谢,这看起来是一个有趣的工具。不过,寻找愿意运行第三方调试诊断工具来捕获信息的客户可能存在一些后勤/政治问题。我认为集成日志记录和日志文件的自愿发送更普遍。
    • 那是相当落后的,至少使用一个广为人知和记录在案的工具,他们会知道它的作用以及可能暴露的内容。自己添加的唯一好处是他们不知道,所以不会想阻止它,这并不是激发你认真对待他们的担忧的信心的好方法。但这取决于你。
    • 关于 SystemEvents 类引起的问题,请参阅 this answer 中的 CheckSystemEventsHandlersForFreeze() 函数,它可以帮助找到根本原因,即导致冻结的确切控件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2013-04-09
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    相关资源
    最近更新 更多