每秒更新WPF标签内容

11

我想每秒刷新标签内容。因此,我定义了以下两个方法。我在Window的构造函数中使用startStatusBarTimer()

代码:

private void startStatusBarTimer()
{
    System.Timers.Timer statusTime = new System.Timers.Timer();

    statusTime.Interval = 1000;

    statusTime.Elapsed += new System.Timers.ElapsedEventHandler(statusTimeElapsed);

    statusTime.Enabled = true;
}

private void statusTimeElapsed(object sender, ElapsedEventArgs e)
{
    lblNow.Content = DateTime.Now.ToString("yyyy/MM/dd");      
}

但是我得到了这个错误:

调用线程无法访问此对象,因为不同的线程拥有它。

怎么回事?或者我该怎么做?


http://www.c-sharpcorner.com/uploadfile/mahesh/timer-in-wpf/ - I4V
1
一个线程无法访问控件,基本上是因为“根”线程已经在控制它,而两个线程不能同时控制它。有一种方法可以访问这些控件,只需谷歌搜索“WPF线程控制”或“C#线程控制”。 - BlueCacti
1
我很好奇为什么你在构造函数中声明“System.Timers.Timer statusTime”,而不是在类定义中声明! - user1451111
2个回答

15
你面临 线程亲和性 问题。由于已在后台线程上调用了经过时间的事件,因此你无法从后台线程访问 UI 控件。你需要将操作放置在 UI 调度程序 上,以便将其分派到 UI 线程。
private void statusTimeElapsed(object sender, ElapsedEventArgs e)
{
    App.Current.Dispatcher.Invoke((Action)delegate
    {
       lblNow.Content = DateTime.Now.ToString("yyyy/MM/dd");   
    });
}

或者

你可以使用专门为此目的构建的DispatcherTimer。 你可以从其Tick事件处理程序访问UI控件。 可以在MSDN这里参考示例。


3

只需使用以下代码刷新WPF应用程序中的任何控件。您必须将此类粘贴到相同的命名空间中。

public static class ExtensionMethods
    {
        private static Action EmptyDelegate = delegate() { };

        public static void Refresh(this UIElement uiElement)
        {
            uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
        }
    }

然后使用以下方式:

lable1.Refresh();

由于某种原因,只有在使用发布版本时,这个对我才有效。当我处于调试模式时,UI 元素不会更新。 - brandonstrong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接