为什么System.Timers.Timer不更新非繁忙的UI?

phi*_*131 4 c# wpf user-interface timer

我一直在寻找原因,但关于stackoverflow上的每一个主题,我都能找到一个忙碌的UI作为原因.我有非常基本的代码,仅用于测试,它根本不会更新UI,即使我确信它不能忙于做其他事情:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    static double t = 0;
    static double dt = 0.1;

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Timer timer = new Timer(5000);
        timer.Enabled = true;
        timer.Elapsed += new ElapsedEventHandler(Update);
        timer.Start();
    }

    void Update(object sender, ElapsedEventArgs e)
    {
        t = t + dt;
        testBlock1.Text = (t).ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

我调试了它并为textBlock1.Text更新设置了一个断点,它确实每隔5秒就会中断,但UI永远不会更新.从代码中可以看出,当我将鼠标移到Button我用来启动计时器时,按钮会显示其典型的"鼠标悬停按钮"动画.为什么会这样,但不是文本更新?

如果有人能引导我到stackoverflow的一个好主题,请这样做,我将在这里删除我的问题,但我找不到任何主题解释为什么这种方法不更新UI即使UI不忙做任何其他.

Jon*_*eet 12

System.Timers.Timer默认情况下不会封送回UI线程.在Windows窗体中,您可以轻松地完成此操作:

Timer timer = new Timer(5000);
timer.SynchronizingObject = this;
Run Code Online (Sandbox Code Playgroud)

...但WPF UI元素没有实现ISynchronizeInvoke,这将阻止它在WPF中为您工作.

您可以使用Dispatcherto to marshal到处理程序中的UI线程,或者您可以使用a DispatcherTimer来开始.


Roh*_*ats 8

对于WPF,您应该使用DispatcherTimer- 也使用您发布的上述代码,我收到cross thread错误,因为elapsed事件是在其他线程上引发而不是UI thread.

private void button1_Click(object sender, RoutedEventArgs e)
{
   DispatcherTimer timer = new DispatcherTimer();
   timer.Interval = new TimeSpan(0, 0, 5);
   timer.Tick += new EventHandler(timer_Tick);
   timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
   t = t + dt;
   txt.Text = (t + dt).ToString();
}
Run Code Online (Sandbox Code Playgroud)

编辑

此外,您可以使用现有代码在UI Dispatcher上封送它 - 如下所示 -

void Update(object sender, ElapsedEventArgs e)
{
    App.Current.Dispatcher.Invoke((Action)delegate()
    {
        t = t + dt;
        txt.Text = (t + dt).ToString();
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 我想我想保留这个答案,因为它也为我的问题提供了简单的代码.总的来说,谢谢你的答案,它的确有效. (2认同)
  • 我更新了我接受的答案,因为提供的代码直接适用于我的问题,再次感谢. (2认同)