假设我有一个 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 并自己计算帧数……这是在监视渲染线程……如果丢帧,那么它可能会告诉您您的系统负担过重……并且您可以相应地限制您的后台工作。
http://blogs.msdn.com/b/jgoldb/archive/2008/09/26/etw-event-tracing-in-wpf.aspx
Why is Frame Rate in WPF Irregular and Not Limited To Monitor Refresh?
使用计时器安排工作
您可以使用@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/