当我们使用Task.Run(()=>{})
开启一个线程,如果线程里面有错误,外面需要处理捕获异常,很自然的方法我们在外部加try{ } Catch(Exception e){ }
,但是这种方法在外部捕获不了异常,如下:
try
{
var task = Task.Run(() =>
{
int a = 10;
int b = 0;
int c = a / b;
});
}
catch
{
MessageBox.Show("出现异常");
}
上面不会出现弹窗出现异常的信息,因为异常信息没有被抛到外面来,针对多线程Task的异常处理
找到了几种处理方法。
1.使用全局多线程异常处理
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
MessageBox.Show(e.Exception.InnerException.Message);
e.SetObserved();
}
这里捕获的e.Exception
是AggregateException
类型的,如果直接获取其Message
,会出现未通过等待任务或访问任务的 Exception 属性观察到任务的异常。因此,终结器线程重新引发了未观察到的异常
,根本就没法知道线程里面出现了什么异常,正确的方法是使用e.Exception.InnerException.Message
,可以知道线程里面具体出现了什么异常.
2.Task.ContinueWith处理
//2.使用ContinueWith(t=>{},TaskContinuationOptions.OnlyOnFaulted)进行异常后的处理
var task2 = Task.Run(() =>
{
throw new ArgumentNullException("参数为Null");
});
task2.ContinueWith(t => { MessageBox.Show(t.Exception.InnerException?.Message); }, TaskContinuationOptions.OnlyOnFaulted);//这个会进行错误处理
3.直接try…catch捕获task.Wait();
//4.Try{ task.Wait(); }Catch(Exception ex){};
CancellationToken ct = new CancellationToken();
var task3 = Task.Run(() => { throw new InvalidOperationException("无效操作"); }, ct);
try
{
task3.Wait(ct);
}
catch (AggregateException ex)
{
MessageBox.Show(ex.InnerException.Message);
}
上面就是常见的几种处理方法.