在UI构造函数中使用Task.Run()时处理异常
本文关键字:处理 异常 Run Task 构造函数 UI | 更新日期: 2023-09-27 18:06:51
我有一个这样调用Task.Run()
的构造函数:
public MyPage() {
Task.Run(() => {
MyHeavyCpuMethod();
});
}
这里,MyPage()
是一个UI组件的构造函数,我不希望MyHeavyCpuMethod()
在我的UI线程上运行,所以我用Task.Run()
卸载它,因为我并不真正关心MyHeavyCpuMethod()
何时完成。
然而,这样,如果MyHeavyCpuMethod()
抛出,我不能处理在返回的任务中的异常。
在这种情况下我如何处理错误?
一个选择是使用async/await…它不能与构造函数一起工作,但是可以在静态方法中工作:
public static async Task<MyPage> CreateInstance()
{
await Task.Run(...);
// Anything else asynchronous you want to use
return new MyPage();
}
然后假设你在异步方法中使用 this,你可以使用:
MyPage page = await MyPage.CreateInstance();
这样,如果cpu绑定任务失败,您甚至无法调用构造函数。在这里,构造函数调用本身被期望是快速的,因为将放在UI线程上(如您所愿)。
另一种方法是,您可以将Task.Run
返回的任务存储为页面中的字段,然后等待后期构造…使用正常的异步异常处理方法
添加一个ContinueWith
,只有当Task
没有运行到完成(抛出异常)时才会触发:
Task.Run(() => MyHeavyCpuMethod())
.ContinueWith(task => { /* some action */ }, TaskContinuationOptions.OnlyOnFaulted);
你的第二个任务也不会在UI线程上运行,根据文档:
创建一个延续,在目标任务完成时异步执行。
您可以使用一个虚拟方法来尝试:
Task.Run(() =>
{
throw new Exception();
}).ContinueWith(t =>
{
Invoke((MethodInvoker)(() => MessageBox.Show("ERROR")));
}, TaskContinuationOptions.OnlyOnFaulted);