假设我有一个WPF应用程序,其中有以下体系结构:
工作线程->队列1 ->队列管理器线程->队列2 -> UI线程
工作器正在监听来自某些服务的数据并在不确定的时间(可以是每秒多次或每几秒几次)接收该数据,然后将其排队到队列1,然后队列管理器可以根据UI线程的“健康状况”来决定调高/降低数据项排队到队列2的速率,UI线程使用该速率来更新UI,可能丢弃一些项,以便在接收太多消息的情况下不会使UI线程不堪重负(例如,它可能会决定检查每个数据消息的时间戳,并仅在消息之间的差异比UI自身更新的最后一个数据项早至少5秒时才将其排入队列2)
UI线程将有一个定时器,该定时器触发一个设置的间隔来使用队列2中的新数据更新UI。我希望能够做的是确定UI自我更新的速度,以测量它的“响应性”,以便调节例如增加/减少定时器间隔,以确定更新UI的频率
假设我的UI有许多控件(网格、图表等)都绑定到UI shell中队列2上的不同过滤/分组数据子集,并且UI在更新这些控件时开始变得无响应并在两次更新之间冻结,我如何从代码中检测到这一点,以便知道如何/何时增加/减少UI更新的间隔?基本上,我如何衡量跨绑定到数据的所有控件重新绑定整个UI所需的时间?
顺便说一句,这是一个好的设计,还是可以改进?有没有其他我可以考虑的策略?
发布于 2012-08-17 02:59:08
我会简单地去掉QueueManager和Queue2。
您所需要的只是一个每隔几毫秒检查一次输入的WPF Dispatcher定时器(而不是Timers.Timer)。您可以静态配置该超时。
然后使Queue1成为阻塞队列,以限制上游的任何内容。
编辑
可以使用certain priority启动调度程序计时器。选择一个较低的值,如Background或ContextIdle,您将永远不会使图形用户界面过载。
然后,只要确保计时器不会超出它的能力范围即可。一次只有1个(或几个)项目。调优此部分,以便GUI将处理尽可能多的内容,但不会超过此部分。运行时调整是免费的,因为您与dispatcher捆绑在一起。
而且(仅在需要时)您可以使用Queue1 = new BlockingCollection<MyItemType>(MaxItems),这样队列就不会被填满。
发布于 2012-08-17 03:07:22
有2个threads...the主UI thread....and的渲染thread....you可能需要查看这两个,以确定您的application...and的响应性,决定如何节流。
测量你的FrameRate
你可以观察ETW事件,或者处理CompositionTarget.Rendering并计算yourself....this正在监控正在丢弃帧的渲染thread...if的帧数,然后它可以告诉你你的系统是overburdened...and的,你可以相应地限制你的后台工作。
使用计时器来安排工作
你可以使用@HenkHolterman提到的DispatcherTimer来监控UI线程上的负载,方法是让它以低于正常的优先级运行,例如Background....when。定时器事件在UI上处理/处理,然后thread....you可以释放/告诉你的后台工作人员做下一项工作。
但是,你的计时器时间间隔太短了,你的系统是overloaded...then的,你可能会得到一个计时器messages...and的积聚,所以当你的eventhandler是called...you时,可能会做太多的工作(除非你保留了最后一次调用它的记录)。
在UI线程上执行委托
或者,你也可以让一个代理在UI线程上以特定的优先级运行(例如,通常是后台)。
如果您使用Dispatcher.BeginInvoke....then,则工作将被放入队列中,并将在所有较高优先级的工作完成时执行。(异步)。
如果你使用Dispatcher.Invoke...then,你的线程将会阻塞,直到你调用的Dispatcher中所有更高优先级的工作都完成了,然后你的委托才会执行。
(后台工作人员将在完成其工作单元后执行此操作,然后代理将告诉后台工作人员执行下一个工作单元)。
这可能比DispatchTimer更好,因为你可以消除一些延迟。使用定时器将具有取决于定时器间隔的等待时间。
然后,根据您找到的内容,您可以调整下一个工作单元。
监视各种系统性能计数器
如果你真的想变得复杂,那么你可以从你的应用程序内部监控各种性能计数器,例如内存的使用,GC收集,etc...and动态地限制你所做的工作量。
有关调度程序的一些背景知识
https://stackoverflow.com/questions/11993530
复制相似问题