.NET Core WPF:后台任务失败时非阻塞显示详情窗口的方案
WPF异步加载任务与异常处理的正确实现
核心改造思路
将按钮点击事件改为异步方法,利用async/await语法在不阻塞UI线程的前提下执行后台任务,同时正常捕获异常并弹出失败窗口。WPF允许事件处理程序使用async void(这是少数合法场景),配合await可自动回到UI上下文,无需额外Dispatcher操作。
修改后的代码实现
Launch.xaml.cs
// 将方法改为async void,适配WPF事件处理 private async void btnDemo_click(object sender, EventArgs e) { ProgressBarVisibility = Visibility.Visible; // UI会立即更新,不再被后续代码阻塞 try { // 如果LoadConfigs是耗时操作,同样包装到Task.Run中异步执行 await Task.Run(() => LoadConfigs()); // 异步执行耗时的COM+数据请求,释放UI线程处理进度条动画 await Task.Run(() => PreCacheEHRData()); // 加载成功,启动主应用 LaunchMainApp(); } catch (Exception ex) { // 回到UI上下文,弹出失败窗口(此时进度条窗口仍保持显示) var failureWindow = new FailureDetailsWindow(); failureWindow.SetErrorInfo($"任务失败:{ex.Message}"); // 自定义错误信息展示逻辑 failureWindow.ShowDialog(); // 根据用户选择执行对应操作 if (failureWindow.IsRetrySelected) { // 重试加载逻辑 btnDemo_click(sender, e); } else { Close(ExitReasons.DATALOADERROR); } } }
关键细节说明
- 异步任务执行:用
await Task.Run()将同步耗时任务转移到后台线程,UI线程在await期间可正常处理进度条动画和其他UI交互。 - 异常捕获:
await会将后台任务的异常抛回UI线程的try/catch块,无需额外处理跨线程异常。 - UI上下文自动切换:
await完成后会自动回到UI线程,因此在catch中可直接创建并显示失败窗口,无需调用Dispatcher.Invoke。 - 加载窗口显示优化:如果需要进度条窗口全程保持显示,需确保其以非模态方式打开(使用
Show()而非ShowDialog()),避免阻塞后续异步逻辑。
额外优化建议
- 如果COM+服务提供原生异步调用方法,优先使用原生异步API替代
Task.Run包装同步方法,提升性能和资源利用率。 - 可将加载逻辑封装为独立的异步服务类,降低UI代码与业务逻辑的耦合度。
内容的提问来源于stack exchange,提问作者user1752971
相关产品推荐
相关产品推荐

