我有一个WPF应用程序,我正在使用.NET Framework 4.0和C#。我的应用程序包含一个带有多个控件的界面。特别是我有一个需要每10秒定期执行一次的任务。为了执行它,我使用System.Windows.Threading.DispatcherTimer
。 ViewModel看起来像这样:
public class WindowViewModel {
protected DispatcherTimer cycle;
public WindowViewModel() {
this.cycle = new DispatcherTimer(DispatcherPriority.Normal,
System.Windows.Application.Current.Dispatcher);
this.cycle.Interval = new TimeSpan(0,0,0,0,10000);
this.cycle.Tick += delegate(object sender, EventArgs e) {
for (int i = 0; i < 20; i++) {
// Doing something
}
};
this.cycle.Start;
}
}
正如我所说,定期调用的例程会做一些事情。特别是那里有一些重要的逻辑导致该例程花费几秒钟来执行和完成。好吧,这是一个不同的线程,所以我应该没问题,界面不应该冻结。
问题是该例程导致视图模型更新。更新了几个数据,相应的View绑定到这些数据。所发生的是所有更新的数据在例程完成时刷新一次。我希望在线程执行期间更新数据。
特别是在那个例程中,我有一个for
周期。在循环的退出处,一切都在界面中更新。怎么做到这一点?我在哪里做错了?
答案 0 :(得分:3)
DispatcherTimer
使用提供的Dispatcher
来运行计时器回调。
如果你看一下Dispatcher
的文档,就会有一个线索:
提供管理 线程
的工作项队列的服务。
因此,通过使用System.Windows.Application.Current.Dispatcher
,您将使用管理UI线程的“工作项队列”的Dispatcher。
要在ThreadPool
中开展工作,您可以使用System.Threading.Timer
或在ThreadPool.QueueUserWorkItem
回调中使用DispatcherTimer
。
如果将此与以下扩展方法结合使用,则在完成繁重的工作量时,可以轻松地将任何特定于UI的内容封送回Dispatcher:
public static class DispatcherEx
{
public static void InvokeOrExecute(this Dispatcher dispatcher, Action action)
{
if (dispatcher.CheckAccess())
{
action();
}
else
{
dispatcher.BeginInvoke(DispatcherPriority.Normal,
action);
}
}
}
...然后
this.cycle.Tick += delegate(object sender, EventArgs e) {
ThreadPool.QueueUserWorkItem(_ => {
for (int i = 0; i < 20; i++) {
// Doing something heavy
System.Windows.Application.Current.Dispatcher.InvokeOrExecute(() => {
//update the UI on the UI thread.
});
}
});
};