WPF Timer与DispatcherTimer
在vm层去渲染view层数据时,子线程直接操作UI线程(主线程),会报一个错误:调用线程无法访问此对象,因为另一个线程拥有该对象
1.使用System.Threading.Timer
在网上查了一下,this.Invoke()可以解决,这里以实现一个倒计时为例子:
<Label Content="{Binding TIME}" HorizontalAlignment="Left" Margin="346,10,0,0" VerticalAlignment="Top" />
private System.Threading.Timer t;
public PageViewModel()
{reduce();
}
private void reduce()
{
t= new System.Threading.Timer(p=>caculateTime(),null, 0, 1000);
}
private void caculateTime()
{
if (this.TIME > 0)
this.TIME--;
else
{
this.t.Dispose();
MainWindowsViewModel.getMWV().mf.Dispatcher.Invoke(new Action(() =>
{
MainWindowsViewModel.getMWV().mf.Navigate(new Uri("page1.xaml", UriKind.Relative));
}));
}
}
在caculateTime中,倒计时结束跳转页面,MainWindowsViewModel为我自己封装好的一个单例对象
2.使用DispatcherTimer
public PageViewModel()
{reduce();
}
private void reduce()
{
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
if (this.TIME > 0)
this.TIME--;
else
{
this.timer.Stop();
MainWindowsViewModel.getMWV().setFrame("page1.xaml");
}
}
倒计时结束关闭子线程,跳转页面
区别在于:
DispatcherTimer是在界面线程中实现,所以可以安全的访问和修改界面的内容;但是DispatcherTimer里面执行的时间过长可能会导致UI假死。
项目GitHub地址:https://github.com/forfcw/.Net/tree/master/WPFTest