最近的工作项目中需要定时更新UI控件中的数据,这时候第一反应肯定会想到去使用System.Timers.Timer定时更新UI控件,但是程序运行后,会发现程序崩溃了。报的异常为“调用线程无法访问此对象,因为另一个线程拥有该对象。”,网上查找了原因,Timer的触发事件与UI不是属于同一个线程,所以说在Timer的触发事件去更新UI时,会造成UI对象被占用的问题。网上说,可以尝试用DispatcherTimer这个定时器去更新UI,于是我做个一个demo测试了一下,果然是可行的。
上面是一个WPF窗口,点击计时按钮,编辑框中显示计时次数
1.使用System.Timers.Timer更新编辑框中的数据
1 namespace Timer 2 { 3 /// <summary> 4 /// MainWindow.xaml 的交互逻辑 5 /// </summary> 6 public partial class MainWindow : Window 7 { 8 System.Timers.Timer timer = null; 9 private static int nCount = 0; 10 public MainWindow() 11 { 12 InitializeComponent(); 13 timer = new System.Timers.Timer(1000); 14 timer.AutoReset = true; 15 timer.Elapsed += new ElapsedEventHandler(TimeAction); 16 } 17 private void TimeAction(object sender, ElapsedEventArgs e) 18 { 19 if (!String.IsNullOrEmpty(txt_TimeCount.Text)) 20 { 21 //计时次数大于10时,则关闭定时器 22 if (Convert.ToInt32(txt_TimeCount.Text) > 10) 23 { 24 timer.Stop(); 25 } 26 } 27 28 txt_TimeCount.Text = Convert.ToString(nCount++); 29 } 30 private void btn_Time_Click(object sender, RoutedEventArgs e) 31 { 32 timer.Start(); 33 } 34 } 35 }
当点击按钮后,会很明显的出现上述所说的异常问题
2.使用DispatcherTimer更新编辑框中的数据
1 namespace Timer 2 { 3 /// <summary> 4 /// MainWindow.xaml 的交互逻辑 5 /// </summary> 6 public partial class MainWindow : Window 7 { 8 DispatcherTimer dispatcherTimer = null; 9 private static int nCount = 0; 10 public MainWindow() 11 { 12 InitializeComponent(); 13 dispatcherTimer = new DispatcherTimer(); 14 dispatcherTimer.Interval = new TimeSpan(0, 0, 1); 15 dispatcherTimer.Tick += new EventHandler(TimeAction); 16 17 } 18 19 private void TimeAction(object sender, EventArgs e) 20 { 21 if (!String.IsNullOrEmpty(txt_TimeCount.Text)) 22 { 23 //计时次数大于10时,则关闭定时器 24 if (Convert.ToInt32(txt_TimeCount.Text) > 10) 25 { 26 dispatcherTimer.Stop(); 27 } 28 } 29 30 txt_TimeCount.Text = Convert.ToString(nCount++); 31 } 32 private void btn_Time_Click(object sender, RoutedEventArgs e) 33 { 34 dispatcherTimer.Start(); 35 } 36 } 37 }
输出结果如下,可以看出程序能够正常的运行