.net DispatcherTimer 与 WPF 应用程序中用于任务调度程序的常规计时器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2258830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:54:36  来源:igfitidea点击:

DispatcherTimer vs a regular Timer in WPF app for a task scheduler

.netwpfmultithreadingtimer

提问by rem

Please, explain the difference between "DispatcherTimer" and "a regular Timer" that @Kent Boogaart meant for using in a multithreading WPF app as a task sheduler in this topic:

请解释@Kent Boogaart 用于在多线程 WPF 应用程序中用作本主题中的任务调度程序的“DispatcherTimer”和“常规计时器”之间的区别:

Advice needed for multi-threading strategy for WPF application

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

in the commentaries to one of the post (quote):

在其中一篇文章的评论中(引用):

-If all the DispatcherTimer does is kick off another thread, what is the point of using the DispatcherTimer? ....those threads don't need to be started on the UI thread. You could just use a regular Timer and avoid interrupting the UI altogether

- 如果 DispatcherTimer 所做的只是启动另一个线程,那么使用 DispatcherTimer 的意义何在?....那些线程不需要在 UI 线程上启动。您可以只使用常规计时器并避免完全中断 UI

What is "a regular timer" that is meant? How they ("DispatcherTimer" and "a regular Timer") differ regarding their impact on UI?

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

(Until reading this post I thought about DispatcherTimer as a natural way of using timers in WPF. What is the cases when this is not true?)

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

回答by Hans Passant

DispatcherTimer is the regular timer. It fires its Tick event on the UI thread, you can do anything you want with the UI. System.Timers.Timer is an asynchronous timer, its Elapsed event runs on a thread pool thread. You have to be very careful in your event handler, you are not allowed to touch any UI component or data-bound variables. And you'll need to use the lock statement where ever you access class members that are also used on the UI thread.

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

In the linked answer, the Timer class was more appropriate because the OP was trying to run code asynchronously on purpose.

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

回答by Akash Kava

Regular Timer's Tick event is actually fired on the thread where the Timer was created, so in the tick event, in order to access anything with the UI, you will have to go through dispatcher.begininvoke as mentioned below.

常规 Timer 的 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();
    });
}

In case of Dispatcher Timer, you can access UI elements without doing begin invoke or invoke as follow...

在 Dispatcher Timer 的情况下,您可以访问 UI 元素而无需执行 begin invoke 或 invoke 如下...

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

DispatcherTimer just provides convenience over Regular Timer to access UI objects easily.

DispatcherTimer 只是提供了比常规计时器更方便的方式来轻松访问 UI 对象。

回答by Simon_Weaver

With .NET 4.5 you can also create an asyncdelegate for your timer if you need to use the new .NET 4.5 awaitfunctionality.

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

        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();