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

rem*_*rem 25 .net wpf multithreading timer

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

WPF应用程序的多线程策略所需的建议

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

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

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

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

Han*_*ant 43

DispatcherTimer是常规计时器.它在UI线程上触发其Tick事件,您可以使用UI执行任何操作.System.Timers.Timer是一个异步计时器,其Elapsed事件在线程池线程上运行.您必须在事件处理程序中非常小心,不允许您触摸任何UI组件或数据绑定变量.并且您将需要使用lock语句,只要您访问也在UI线程上使用的类成员.

在链接的答案中,Timer类更合适,因为OP试图故意异步运行代码.


Aka*_*ava 31

常规计时器的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();
    });
}
Run Code Online (Sandbox Code Playgroud)

在Dispatcher Timer的情况下,您可以访问UI元素而无需开始调用或调用如下...

DispatcherTimer_Tick(object sender, EventArgs e)
{
    txtBox1.Text = "Count " + i.ToString();
    // no error here..
}
Run Code Online (Sandbox Code Playgroud)

DispatcherTimer提供了方便的常规计时器,可以轻松访问UI对象.


Sim*_*ver 16

使用.NET 4.5,async如果需要使用新的.NET 4.5 await功能,还可以为计时器创建委托.

        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(20);
        timer.Tick += new EventHandler(async (object s, EventArgs a) =>
        {
            Message = "Updating...";
            await UpdateSystemStatus(false);  
            Message = "Last updated " + DateTime.Now;              
        });
        timer.Start();
Run Code Online (Sandbox Code Playgroud)