C#中如何从System.Timer获取对象并在主线程使用及更新UI
问题原因
System.Timers.Timer的Elapsed事件在后台线程执行,而WPF的UI控件(如dataGrid_Pending)仅允许创建它的主线程(UI线程)进行访问和更新,直接在后台线程操作UI控件会导致无法更新界面,甚至引发线程安全异常。
解决方案
有两种常用的处理方式:
方式1:通过Dispatcher切回UI线程更新
在后台线程获取数据后,使用Dispatcher将UI更新操作调度回主线程执行:
private void UpdatePending(Object source, System.Timers.ElapsedEventArgs e) { DataTable pending = new Repository().GetPending(); if (pending?.Rows.Count > 0) { // 调度UI更新操作到主线程 Application.Current.Dispatcher.Invoke(() => { dataGrid_Pending.DataContext = pending; }); } }
同时建议调整构造函数顺序,先初始化控件再启动定时器,避免控件未初始化时触发事件:
public MainWindow() { InitializeComponent(); Timer execute = new Timer(); execute.Interval = 5000; execute.Elapsed += UpdatePending; execute.Start(); }
方式2:使用DispatcherTimer(更适合WPF场景)
DispatcherTimer的Tick事件直接在UI线程触发,无需手动切换线程,更适合WPF的UI定时更新需求:
public MainWindow() { InitializeComponent(); DispatcherTimer execute = new DispatcherTimer(); execute.Interval = TimeSpan.FromSeconds(5); execute.Tick += UpdatePending; execute.Start(); } private void UpdatePending(object sender, EventArgs e) { DataTable pending = new Repository().GetPending(); if (pending?.Rows.Count > 0) { dataGrid_Pending.DataContext = pending; } }
内容的提问来源于stack exchange,提问作者PeterSchwennesen
相关产品推荐
相关产品推荐

