WinUI 3定时器回调更新TextBlock文本触发COMException异常问题
问题原因
抛出System.Runtime.InteropServices.COMException的核心原因是:System.Timers.Timer和System.Threading.Timer的回调均运行在线程池工作线程,而WinUI 3的UI控件有严格的线程亲和性限制,仅允许在创建控件的UI主线程上修改控件属性,跨线程直接操作控件就会触发该异常,这也是你更换两种线程定时器仍然报错的原因。你找到的旧方案大多面向WPF、UWP平台,WinUI 3的线程调度API有变更,直接套用自然无法生效。
修复方案
方案1:使用WinUI 3原生DispatcherTimer(优先推荐)
这是实现UI定时更新最简单的方案,DispatcherTimer是框架专为UI交互场景设计的定时器,Tick回调默认就在UI线程执行,无需额外做线程调度,直接修改控件属性即可正常运行:
public static DateTime startTime; // 需引用Microsoft.UI.Xaml命名空间 private readonly DispatcherTimer _timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) }; // 在页面/控件构造函数或者OnLoaded事件里绑定事件、启动定时器 public MainPage() { InitializeComponent(); _timer.Tick += Timer_Tick; _timer.Start(); } private void Timer_Tick(object sender, object e) { timerLabel.Text = DateTime.Now.Subtract(startTime).ToString(@"hh\:mm\:ss"); }
方案2:保留原有线程定时器,手动调度更新到UI线程
如果你的业务逻辑必须使用线程池定时器,可以在回调中通过DispatcherQueue把UI更新操作封送到UI线程执行:
public static DateTime startTime; System.Timers.Timer timer = new System.Timers.Timer(1000); timer.AutoReset = true; timer.Elapsed += Timer_Tick; timer.Start(); private async void Timer_Tick(object sender, EventArgs e) { DispatcherQueue.TryEnqueue(() => { timerLabel.Text = DateTime.Now.Subtract(startTime).ToString(@"hh\:mm\:ss"); }); }
注意:WinUI 3中负责跨线程UI调度的是
DispatcherQueue,而非WPF/UWP旧方案里的Dispatcher,这是多数旧教程在WinUI 3环境下失效的核心原因。
内容的提问来源于stack exchange,提问作者Ricky Kresslein
相关产品推荐
相关产品推荐

