关于 c#:Do long running process with Task 并在有异常时显示异常

Do long running process with Task and showing Exception if there is one

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

1
2
3
4
5
6
7
8
9
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 阻塞的情况下继续工作。如果有问题(异常)会在长时间运行的进程结束后显示(正常情况下不会有异常)

这是我使用它的正确方式还是我必须以其他方式使用它?有什么问题,我可以通过这种方式解决,我现在看不到吗?


这将起作用,因为您正在显式检查 Task.Exception,这将防止未观察到异常。

我会在这里提出一些建议。

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

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

其次,你不需要 task:

上的闭包

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

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

1
2
3
4
5
// 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,则可以:

1
2
3
4
5
6
7
8
9
10
11
try
{
    await Task.Factory.StartNew(() => {
           // long running process
           throw new Exception("test"); // throwing TestException
        }, TaskCreationOptions.LongRunning);
}
catch(Exception error)
{
      MyErrorHandler(error);
}