在UI构造函数中使用Task.Run()时处理异常

时间:2015-08-07 20:39:03

标签: c# asynchronous

我有一个像这样调用Task.Run()的构造函数:

public MyPage() {
    Task.Run(() => {
        MyHeavyCpuMethod();
    });
}

此处,MyPage()是UI组件的构造函数,我不希望MyHeavyCpuMethod()在我的UI线程上运行,因此我将其Task.Run()卸载到因为MyHeavyCpuMethod()完成时我并不在乎。

但是,如果MyHeavyCpuMethod()抛出,我就无法处理返回的Task中的异常。

在这种情况下如何进行错误处理?

2 个答案:

答案 0 :(得分:3)

一个选项是使用async / await ...它不能与构造函数一起使用,但可以在静态方法中工作:

public static async Task<MyPage> CreateInstance()
{
    await Task.Run(...);
    // Anything else asynchronous you want to use
    return new MyPage();
}

然后假设你从异步方法中使用这个,你可以使用:

MyPage page = await MyPage.CreateInstance();

这样,如果CPU绑定任务失败,你甚至不会进入构造函数调用。构造函数调用本身在这里应该很快,因为在UI线程上(如你所愿)。

替代方法,您可以将Task.Run返回的任务存储为页面中的字段,然后等待构建后...使用正常的异步异常处理方法。

答案 1 :(得分:0)

添加ContinueWith只会在Task未完成运行时触发(引发异常):

Task.Run(() => MyHeavyCpuMethod())
    .ContinueWith(task => { /* some action */  }, TaskContinuationOptions.OnlyOnFaulted);

根据the documentation

,您的第二个任务也不会在UI线程上运行
  

创建在目标任务完成时异步执行的延续。

您可以使用虚拟方法进行尝试:

Task.Run(() =>
{
      throw new Exception();
}).ContinueWith(t =>
{
    Invoke((MethodInvoker)(() => MessageBox.Show("ERROR")));
}, TaskContinuationOptions.OnlyOnFaulted);