请解释“DispatcherTimer”和“常规计时器”之间的区别,@ Kent Boogaart打算在多线程WPF应用程序中使用它作为本主题中的任务参与者:
Advice needed for multi-threading strategy for WPF application
在其中一篇帖子的评论中(引用):
- 如果所有DispatcherTimer都启动另一个线程,那么使用DispatcherTimer有什么意义呢? ....那些线程不需要在UI线程上启动。您可以使用常规计时器并避免完全中断用户界面
什么是“常规计时器”?他们(“DispatcherTimer”和“常规计时器”)对UI的影响有何不同?
(在阅读这篇文章之前,我认为DispatcherTimer是在WPF中使用计时器的一种自然方式。如果不是这样的情况会是什么情况?)
答案 0 :(得分:42)
DispatcherTimer是常规计时器。它在UI线程上触发其Tick事件,您可以使用UI执行任何操作。 System.Timers.Timer是一个异步计时器,其Elapsed事件在线程池线程上运行。您必须在事件处理程序中非常小心,不允许您触摸任何UI组件或数据绑定变量。并且你需要使用lock语句来访问也在UI线程上使用的类成员。
在链接的答案中,Timer类更合适,因为OP试图故意异步运行代码。
答案 1 :(得分:30)
常规计时器的Tick事件实际上是在创建Timer的线程上触发的,因此在tick事件中,为了使用UI访问任何内容,您将必须通过dispatcher.begininvoke,如下所述。
RegularTimer_Tick(object sender, EventArgs e)
{
txtBox1.Text = "count" + i.ToString();
// error can not access
// txtBox1.Text property outside dispatcher thread...
// instead you have to write...
Dispatcher.BeginInvoke( (Action)delegate(){
txtBox1.Text = "count " + i.ToString();
});
}
如果是Dispatcher Timer,您可以访问UI元素而无需开始调用或调用如下...
DispatcherTimer_Tick(object sender, EventArgs e)
{
txtBox1.Text = "Count " + i.ToString();
// no error here..
}
DispatcherTimer提供了方便的常规计时器,可以轻松访问UI对象。