c# - 如何检测无响应的 UI 更新?

标签 c# .net wpf multithreading

假设我有一个 WPF 应用程序,其中我具有以下架构:

[工作线程] -> [队列 1] -> [队列管理器线程] -> [队列 2] -> [UI 线程]

Worker 正在监听来自某些服务的数据并在不确定的时间接收该数据(可能是每秒多次或每隔几秒几次)然后将其排队到队列 1,然后是队列管理器,具体取决于“UI 线程的“健康”可能决定提高/降低数据项排队到队列 2 的速率,UI 线程使用队列 2 更新 UI,可能会丢弃一些项目,以免淹没 UI 线程事件它接收到太多消息(例如,它可能决定检查每条数据消息的时间戳,并且仅在消息之间的差异比 UI 自身更新的最后一个数据项早至少 5 秒时才将其排入队列 2 )

UI 线程将有一个计时器,该计时器会触发一个设定的时间间隔,以使用来自队列 2 的新数据更新 UI。我希望能够做的是确定 UI self 更新的速度,以衡量它的“响应性”以限制例如增加/减少关于更新 UI 的频率的计时器间隔

假设我的用户界面有很多控件(网格、图表等)都绑定(bind)到我的用户界面外壳中队列 2 上不同过滤/分组的数据子集,并且在更新这些控件时用户界面开始变得无响应并在更新之间卡住,如何我可以从代码中检测到这一点,以便了解如何/何时增加/减少 UI 更新的间隔吗?基本上,我如何测量跨绑定(bind)到数据的所有控件重新绑定(bind)整个 UI 需要多长时间?

顺便说一句,这是一个好的设计还是可以改进?我可以考虑其他策略吗?

最佳答案

有 2 个线程……主 UI 线程……和渲染线程……您可能需要查看这两个线程以确定应用程序的响应能力……并决定如何节流。

测量帧率

您可以观察 ETW 事件,或处理 CompositionTarget.Rendering 并自己计算帧数……这是在监视渲染线程……如果丢帧,那么它可能会告诉您您的系统负担过重……并且您可以相应地限制您的后台工作。

使用计时器安排工作

您可以使用@HenkHolterman 提到的 DispatcherTimer 来监控 UI 线程上的负载,方法是让它以低于 Normal 的优先级运行,例如后台....当在 UI 线程上处理/处理计时器事件时....然后您可以释放/告诉您的后台工作人员执行下一项工作。

但是要小心......如果你的定时器间隔太小......并且你的系统重载......那么你可能会得到一个定时器消息......所以当你的事件处理程序被调用时......你可能做了太多工作(除非你保留了上次调用它的记录)。

在 UI 线程上执行委托(delegate)

或者,您可以让委托(delegate)以特定优先级(例如,通常是后台)在 UI 线程上运行。

如果您使用 Dispatcher.BeginInvoke....,那么工作将被放入队列中,并在所有优先级更高的工作完成后执行。 (异步)。

如果您使用 Dispatcher.Invoke...那么您的线程将阻塞,直到您调用的 Dispatcher 中所有更高优先级的工作都已完成,然后您的委托(delegate)才会执行。

(您的后台工作人员会在完成其工作单元后执行此操作,然后委托(delegate)会告诉您的后台工作人员执行下一个工作单元)。

这可能比 DispatchTimer 更好,因为您可以消除一些延迟……即使用计时器会有延迟,具体取决于计时器间隔。

然后根据您的发现,您可以调整下一个工作单元。

监控各种系统性能计数器

如果你真的想变得复杂,那么你可以从你的应用程序内部监控各种性能计数器,例如使用内存、GC 收集等...并动态限制您所做的工作量。

Dispatcher 的一些背景

关于c# - 如何检测无响应的 UI 更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11993530/

相关文章:

c# - 为什么这行得通?方法重载+方法覆盖+多态

c# - .Net 桌面应用程序和 Web 应用程序之间的技术区别是什么?

wpf - WPF Xaml 的 StringFormat 功能是否适用于 Label.Content?

c# - 当绑定(bind)数据更改时,用户控件上的依赖属性不更新该属性

c# - 如何在单独的线程中加载多个 3D 几何图形而不会遇到线程所有权问题?

c# - AutoMapper - 展平/展平列表

c# - 基于wf 4+的开源工作流引擎项目

.net - 如何模拟 .net 应用程序的低内存?

c# - 引用另一个程序集中全局命名空间中的公共(public)静态类

asp.net - 将 ASP.NET 网站应用程序导入到 MVC 应用程序中的 View