C# 为什么';t System.Timers.Timer更新非忙用户界面?

C# 为什么';t System.Timers.Timer更新非忙用户界面?,c#,wpf,user-interface,timer,C#,Wpf,User Interface,Timer,我一直在寻找一个原因,但关于stackoverflow的每一个主题,我都会发现一个繁忙的UI是原因。 我有非常基本的代码,仅用于测试,它不会更新UI,尽管我确信它不会忙于做其他事情: public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } static double t = 0; static double dt =

我一直在寻找一个原因,但关于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();
    }
}
我调试了它,并将断点设置为
textBlock1.Text
update,它确实每5秒中断一次,但UI从未更新。从代码中可以看出,当我将鼠标移到我用来启动计时器的
按钮上时,该按钮会显示其典型的“鼠标移到按钮”动画。为什么会发生这种情况,而不是文本更新

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

默认情况下不会封送回UI线程。在Windows窗体中,您可以非常轻松地执行此操作:

Timer timer = new Timer(5000);
timer.SynchronizingObject = this;
。。。但是WPF UI元素没有实现
ISynchronizeInvoke
,这将阻止它在WPF中为您工作


您可以使用
Dispatcher
封送到处理程序中的UI线程,也可以使用一个作为开始。

对于WPF,您应该使用
dispatchermer
- 同样,对于您发布的上述代码,我得到了一个
跨线程
错误,因为
已用
事件是在其他线程上而不是在
UI线程
上引发的

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

此外,您可以在UI Dispatcher上使用现有代码对其进行封送处理,如下所示-

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

@它会,但行
(t+dt).ToString()t=t+dt之后,code>几乎没有意义
…文本框的初始文本是“textbox”,t在每次更新时使用
t=t+dt
进行更新,正如我在问题中所看到的那样。@Adamhuldsworth这是一个小错误,我更正了它,谢谢。
计时器
是它自己的线程。您阅读的问题答案不正确,问题是,您试图在单独的线程中更新
UI线程。解决方案是在WPF窗口中使用
调度程序
,在Win32窗体中使用
调用
。我不太明白“问题的答案”是什么意思,但本页上的两个答案都解释了这是一个跨线程问题,因此这两个答案实际上都直接适用于我的问题。但有趣的是,这将导致一个跨线程的UI访问错误,而OP没有说明这一点。或者这只是WinForms中的情况吗?@Adamhuldsworth:这不取决于构建配置吗?我认为在WinForms下是这样的-不确定WPF。但是计时器在UI线程中引发了一个事件,这不应该独立于计时器在不同线程中运行的事实来更新UI吗?@phil13131:这实际上是Jon试图指出的问题。您正在使用的
计时器
不会隐式更改线程,因此方法处理程序会在另一个线程上引发。@Ramhound:我看不到这里有死锁的迹象。你认为为什么会这样呢?你可能会考虑删除这个答案,然后只是投票支持由乔恩提供的答案,因为他在最后一句话中说,OP应该只使用<代码> DexChutier-< /代码>。我想我会保留这个答案,因为它也为我的问题提供了简单的代码。总的来说,谢谢你的回答,它是有效的。我将我接受的答案更新为你的答案,因为提供的代码直接适用于我的问题,再次感谢。