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中为您工作.
您可以使用Dispatcher
to to marshal到处理程序中的UI线程,或者您可以使用a DispatcherTimer
来开始.
对于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)