DispatcherTimer与WPF应用程序中的常规Timer相关的任务调度程序

时间:2010-02-13 19:57:53

标签: .net wpf multithreading timer

请解释“DispatcherTimer”和“常规计时器”之间的区别,@ Kent Boogaart打算在多线程WPF应用程序中使用它作为本主题中的任务参与者:

Advice needed for multi-threading strategy for WPF application

在其中一篇帖子的评论中(引用):

- 如果所有DispatcherTimer都启动另一个线程,那么使用DispatcherTimer有什么意义呢? ....那些线程不需要在UI线程上启动。您可以使用常规计时器并避免完全中断用户界面

什么是“常规计时器”?他们(“DispatcherTimer”和“常规计时器”)对UI的影响有何不同?

(在阅读这篇文章之前,我认为DispatcherTimer是在WPF中使用计时器的一种自然方式。如果不是这样的情况会是什么情况?)

2 个答案:

答案 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对象。