繁体   English   中英

查找哪个模块阻止了UI线程

[英]Find which module is blocking the UI thread

这是一个两部分问题:

  • 我正在做一个大项目,在这个项目中,由不同团队开发的多个插件被装入一个通用容器外壳中。 有时我会看到我的UI更新被阻止,因为有多个并行的UI更新,我想知道是否有办法找到哪个组件阻止了ui线程

  • 在.net中,我如何创建需要进行专门的UI密集工作的单独的UI线程?

非常感谢您的帮助。 谢谢。

使用调试器。 当您发现它阻塞时,请进行Debug + Break All。 然后Debug + Windows + Threads并选择主线程。 调用堆栈窗口将显示正在执行的操作。

一个极端的情况是,这些插件使用了大量对Control.Begin / Invoke或Dispatcher.Begin / Invoke的调用。 在这种情况下,您的UI线程不会被阻塞,只是被派遣委托目标的请求所淹没。 而且不再能够正常工作,例如重新粉刷窗户以及响应鼠标和键盘事件。 除了与插件作者合作以使他们修补自己的方法外,您无能为力。

您已经有一个UI线程,该线程创建了第一个窗口。 创建具有自己窗口的其他线程是可能的,但是会导致Z轴顺序无法解决的问题(一个窗口将在另一个应用程序的窗口下方消失)以及大量的窗口互操作线程问题。

Visual Studio 2010(在较高的SKU中)包含检查此功能。 如果在并发分析器下运行程序,则可以确切地看到发生死锁时哪些线程正在等待哪些锁。 此外,它将突出显示死锁(我相信是亮红色的),以便于跟踪。

您可以采取的一种方法(尽管可能需要重新设计)是禁止所有插件逻辑在UI线程中运行。 所有需要更新UI的操作都必须通过定义良好的服务接口进行路由,这些服务接口可以解释,调度甚至限制UI更新。 仅当您的插件不是完全以UI为中心并且您具有一个服务模型,该服务模型可让您将插件正在操作的数据与该数据的可视化隔离开来时,这才是切实可行的。 在不了解您的应用程序的情况下,我无法给出更具体的建议。

这是我很快想到的两个可能的解决方案。 我相信还有其他同样有效的解决方案。

选项1:代替使用push模型(通过ISynchronizeInvoke方法),切换到pull(或轮询)模型,在该模型中,UI会向插件查询更新。 这具有以下优点。

  • 它打破了UI和Control.Invoke施加的工作线程/插件线程之间的紧密耦合。
  • 它将更新UI线程的责任放在了它应该属于的UI线程上。
  • UI线程可以指示更新的时间和频率。
  • UI消息泵不会像工作线程/插件线程启动的封送处理技术那样被超限运行。
  • 辅助线程/插件线程不必等待确认已执行更新,然后再继续执行下一步(即,UI和辅助线程/插件线程都可获得更高的吞吐量)。

选项2:让插件接受ISynchronizeInvoke实例,而不是实际的FormControl 将使用专用线程和充当插件与UI之间的缓冲区的队列来实现此特殊的同步对象。 它将通过普通的InvokeBeginInvoke方法接受更新消息,这意味着您可以使插件体系结构和接口大部分保持完整,然后在进行某种类型的过滤,合并和限制操作后将这些消息转发到UI。 随着UI和插件线程工作负载的变化,同步对象中存在的更新消息的数量会起伏不定。 随着消息速率的提高,它可能会足够聪明地更改其转发策略。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM