4

我正在测试在我的应用程序中使用任务。现在,我已经完成了休耕:

var task = Task.Factory.StartNew(() => {
   // long running process
   throw new Exception("test"); // throwing TestException
});
task.ContinueWith(x => MyErrorHandler(task.Exception), TaskContinuationOptions.OnlyOnFaulted);

void MyErrorHandler(Exception error) {
   MessageBox.Show(error.Message);
}

这个想法是,将执行长时间运行的进程,并且用户可以在没有任何 UI 阻塞的情况下继续工作。如果有问题(异常),它将在长时间运行的过程完成后显示(在正常情况下,不会有异常)

这是我使用它的正确方式还是我必须以另一种方式来做?有什么问题,我可以通过这种方式得到,我现在看不到吗?

4

1 回答 1

8

当您明确检查时,这将起作用,Task.Exception这将防止异常未被观察到。

我会在这里提出几个建议。

首先,如果这确实是一项长期运行的任务,您可能需要指定:

var task = Task.Factory.StartNew(() => {
   // long running process
   throw new Exception("test"); // throwing TestException
}, TaskCreationOptions.LongRunning);

其次,您不需要关闭task

// use x.Exception, since x is the task
task.ContinueWith(x => MyErrorHandler(x.Exception), TaskContinuationOptions.OnlyOnFaulted);

您可能还希望在主线程上运行它,特别是如果您决定要使用更精细的东西(在您的 UI 中)进行报告:

// This will work if MyErrorHandler uses a UI control, since it'll marshal back to the current synchronization context
task.ContinueWith(x => MyErrorHandler(x.Exception), 
    CancellationToken.None,
    TaskContinuationOptions.OnlyOnFaulted,
    TaskScheduler.FromCurrentSynchronizationContext());

(仅当您要在错误处理程序中使用 UI 控件等时才需要这样做。)

另外 - 如果您使用 .NET 4.5 或 .NET 4 的异步目标包,您可以通过使用新的async/await支持来简化此操作。如果将方法标记为async,则可以执行以下操作:

try
{
    await Task.Factory.StartNew(() => {
           // long running process
           throw new Exception("test"); // throwing TestException
        }, TaskCreationOptions.LongRunning);
}
catch(Exception error)
{
      MyErrorHandler(error);
}
于 2013-02-13T17:46:34.027 回答