【发布时间】:2018-04-25 02:07:17
【问题描述】:
所以我调用Dispatcher.BeginInvoke() 在Timer.Elapsed 事件中执行一些UI 操作。计时器滴答作响,BeginInvoke() 的多个新实例可能会在之前的调用完全处理之前堆积起来。在当前调用的处理完成后,我总是对只选择BeginInvoke() 的最新实例感兴趣,即消息队列中任何以前未处理的实例都应该被丢弃。
清空 Dispatcher 的 BeginInvoke 队列以实现此目的的正确方法是什么?
为了演示一个示例,假设我每秒多次从 Timer.Elapsed 事件中的传感器读取值,然后更新复杂的 UI 以显示读取的值。此 UI 更新操作需要一些时间,在此期间,读取值的一个或多个新实例会堆积在调度程序队列中以进行渲染。显然,当我从传感器获得更新的值时,我想丢弃等待队列中的所有实例,只保留当前实例,以便在处理器空闲时发送以进行渲染。
【问题讨论】:
-
“正确的方法”?空无一人。你的问题太宽泛了,可能的答案太多了。到目前为止,您尝试过什么来实现这一目标? ...
-
... 例如,您是否尝试过设置一个代表队列,当队列为空时您只调用
BeginInvoke()?或者甚至可能只是一个字段(因为您只关心最新的),仅当字段为null时才调用BeginInvoke()?或者您可能已经尝试过,因为无论如何您都无法在计时器间隔内完成操作,使用更长的间隔?或者可能根本不使用计时器,而只是在每次操作结束时再次调用BeginInvoke()?或者,也许您应该有一个单独的 UI 更新计时器,以较慢的间隔复制传感器读数以进行 UI 显示 -
@PeterDuniho:在读取下一个值之前,我已经等不及操作完成了。计时器是一种通用时钟,它会以恒定的速率滴答作响。
-
@PeterDuniho:我也意识到这听起来有点宽泛。但我正在专门寻找一种清除调度程序队列的方法。
-
Timer.AutoReset 属性非常致命,将其初始化为 true 并不是一个好的设计决策。您必须自己将其显式设置为 false。在调用的代码中调用 Start() 以使计时器再次计时。请记住,当您所做的只是让代码在 UI 线程上运行时,使用此 Timer 并没有任何好处,请改用 DispatcherTimer。
标签: c# wpf multithreading synchronization invoke