Task Parallel Library (TPL) 中,当你使用async/await 语法关键字时,你可能遇到以下异常处理的情况: Catch 块只会处理第一个异常而忽略其它的异常。来看下面代码块:
1: private static async void TestCatchExceptionWithTPL()
2: {
3: try
4: {
5: await Task.Factory.StartNew(() =>
6: {
7: Task.Factory.StartNew(() =>
8: { throw new NullReferenceException(); },
9: TaskCreationOptions.AttachedToParent);
10: Task.Factory.StartNew(() =>
11: { throw new ArgumentException(); },
12: TaskCreationOptions.AttachedToParent);
13: });
14: }
15: catch (AggregateException aex)
16: {
17: // this catch will never be target
18: }
19: catch (Exception ex)
20: {
21: Console.WriteLine("## {0} ##", ex.GetType().Name);
22: }
23: }
1: try
2: {
3: Task t = Task.Factory.StartNew(() =>
4: {
5: Task.Factory.StartNew(() =>
6: { throw new NullReferenceException(); },
7: TaskCreationOptions.AttachedToParent);
8: Task.Factory.StartNew(() =>
9: { throw new ArgumentException(); },
10: TaskCreationOptions.AttachedToParent);
11: });
12: await t.ContinueWith(tsk => { if (tsk.Exception != null) throw tsk.Exception; });
13: }
14: catch (AggregateException ex)
15: {
16: foreach (var exc in ex.Flatten().InnerExceptions)
17: {
18: Console.WriteLine(exc.GetType().Name);
19: }
20: }
注意上面12行代码,使用了CoutinueWith方法,为了让代码更加简洁了,我们可以写一个扩展方法:
/// <summary>
/// ThrowMultiple
/// </summary>
/// <param name="t">Task</param>
/// <returns>Task type</returns>
public static Task ThrowMultiple(this Task t)
{
return t.ContinueWith(tsk => { if (tsk.Exception != null) throw tsk.Exception; });
}
/// <summary>
/// ThrowMultiple
/// </summary>
/// <typeparam name="T">Task this</typeparam>
/// <param name="t">Task t</param>
/// <returns>Task generic</returns>
public static Task<T> ThrowMultiple<T>(this Task<T> t)
{
return t.ContinueWith(tsk =>
{
if (tsk.Exception != null)
throw tsk.Exception;
return tsk.Result;
});
}
然后代码就是变成这样了:
1: try
2: {
3: await Task.Factory.StartNew(() =>
4: {
5: Task.Factory.StartNew(() =>
6: { throw new NullReferenceException(); },
7: TaskCreationOptions.AttachedToParent);
8: Task.Factory.StartNew(() =>
9: { throw new ArgumentException(); },
10: TaskCreationOptions.AttachedToParent);
11: }).ThrowMultiple();
12: }
13: catch (AggregateException aex)
14: {
15: // this catch will never be target
16: }
17: catch (Exception ex)
18: {
19: Console.WriteLine("## {0} ##", ex.GetType().Name);
20: }
有看到上面代码11行的变化为我们扩展方法。就这么简单,以上代码在Vs2012下 .net framework 4.5 version 下测试通过,希望对你开发有帮助。
您可能感兴趣的文章:
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。