我有一个带有显示当前时间的文本块的
WPF应用程序.所述文本块绑定到ViewModel上的DependencyProperty.当然我需要不断更新时间,所以我使用了一个定时器(System.Threading.Timer),如下所示:
public MainViewModel()
{
_dateTimer = new Timer(_dateTimer_Tick, null, 0, 60000);
}
void _dateTimer_Tick(object sender)
{
Time = DateTime.Now.ToString("HH:mm");
Date = DateTime.Now.ToString("D");
}
问题是,当调用回调时,应用程序退出… bummer(输出说:“在WindowsBase.dll中发生类型’System.InvalidOperationException’的第一次机会异常”就在它即将写入Time DP时) .
如果我使用DispatcherTimer一切正常.我不介意使用DispatcherTimer,它只是应用程序非常大,我想尽可能地调整其性能.据我所知,我没有访问UI线程(我只是更新属性),因此不需要DispatcherTimer.
我错过了什么吗?
谢谢.
编辑:
属性定义如下:
public string Time
{
get { return (string)GetValue(TimeProperty); }
set { SetValue(TimeProperty, value); }
}
// Using a DependencyProperty as the backing store for Time. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TimeProperty =
DependencyProperty.Register("Time", typeof(string), typeof(MainViewModel), new UIPropertyMetadata(""));
(日期是一样的)
最佳答案 计时器回调正在一个不是UI线程的线程上执行,这会导致问题;尽管你只是“更新一个属性”,但这种情况发生的原因是因为这样的调用创建了一个调用链,即通知感兴趣的各方对属性的更改,在本例中是属性UI,因此,范围会冒泡,导致不适当的跨线程调用.
要克服这个问题,可以在timer构造函数中指定Window的Dispatcher作为state参数的参数,然后使用Dispatcher.Invoke.
例如…
public MainViewModel()
{
_dateTimer = new Timer(_dateTimer_Tick, Dispatcher, 0, 60000);
}
void _dateTimer_Tick(object state)
{
((Dispatcher)state).Invoke(UpdateUI);
}
void UpdateUI()
{
Time = DateTime.Now.ToString("HH:mm");
Date = DateTime.Now.ToString("D");
}
编辑:
使用DiskcherTimer,正如Henk所建议的那样,甚至可以自己考虑,但很可能是去这里的方式 – 但是我根本不知道这种类型,因此无法在我的答案中证明.关于DispatcherTimer和性能,您的担忧是基于什么原因建立的?