【问题标题】:DispatcherTimer vs a regular Timer in WPF app for a task schedulerDispatcherTimer 与 WPF 应用程序中用于任务调度程序的常规 Timer
【发布时间】:2010-02-13 19:57:52
【问题描述】:

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

Advice needed for multi-threading strategy for WPF application

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

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

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

(在阅读这篇文章之前,我一直认为 DispatcherTimer 是在 WPF 中使用计时器的一种自然方式。在哪些情况下这不是真的?)

【问题讨论】:

    标签: .net wpf multithreading timer


    【解决方案1】:

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

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

    【讨论】:

    • 请注意,“触摸”包括设置 MVVM 视图模型属性,因此在使用 DispatcherTimer 时你很好,但使用 Timer 你甚至不能这样做
    • @Simon_Weaver 如果它是一个基本的字符串/数字/布尔属性,那么更改计时器回调中的值就可以正常工作,即使回调不在 UI 线程上运行。确实,您可能会遇到类似 ObservableCollection 属性的问题。
    【解决方案2】:

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

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

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

    DispatcherTimer 比常规定时器更方便地访问 UI 对象。

    【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    猜你喜欢
    • 2016-07-28
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    相关资源
    最近更新 更多