Chapter 16, "Errors and Exceptions," provides detailed coverage of errors and exception handling. However, in the context of asynchronous methods, you should be aware of some special handling of errors.

Let's start with a simple method that throws an exception after a delay (code file ErrorHandling/Program.cs):


static async Task ThrowAfter(int ms, string message)
{
await Task.Delay(ms);
throw new Exception(message);
}

If you call the asynchronous method without awaiting it, you can put the asynchronous method within a try/catch block—and the exception will not be caught. That's because the method DontHandle has already completed before the exception from ThrowAfter is thrown. You need to await the ThrowAfter method, as shown in the following example:


private static void DontHandle()
{
try
{
ThrowAfter(200, "first");
// exception is not caught because this method is finished
// before the exception is thrown
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
  Warning 

Asynchronous methods that return void cannot be awaited. The issue with this is that exceptions that are thrown from async void methods cannot be caught. That's why it is best to return a Task type from an asynchronous method. Handler methods or overridden base methods are exempted from this rule.

Handling Exceptions with Asynchronous Methods

A good way to deal with exceptions from asynchronous methods is to use await and put a try/catch statement around it, as shown in the following code snippet. The HandleOneError method releases the thread after calling the ThrowAfter method asynchronously, but it keeps the Task referenced to continue as soon as the task is completed. When that happens (which in this case is when the exception is thrown after two seconds), the catch matches and the code within the catch block is invoked:


private static async void HandleOneError()
{
try
{
await ThrowAfter(2000, "first");
}
catch (Exception ex)
{
Console.WriteLine("handled {0}", ex.Message);
}

}

Exceptions with Multiple Asynchronous Methods

What if two asynchronous methods are invoked that each throw exceptions? In the following example, first the ThrowAfter method is invoked, which throws an exception with the message first after two seconds. After this method is completed, the ThrowAfter method is invoked, throwing an exception after one second. Because the first call to ThrowAfter already throws an exception, the code within the try block does not continue to invoke the second method, instead landing within the catch block to deal with the first exception:


private static async void StartTwoTasks()
{
try
{
await ThrowAfter(2000, "first");
await ThrowAfter(1000, "second"); // the second call is not invoked
// because the first method throws
// an exception
}
catch (Exception ex)
{
Console.WriteLine("handled {0}", ex.Message);
}
}

Now let's start the two calls to ThrowAfter in parallel. The first method throws an exception after two seconds, the second one after one second. With Task.WhenAll you wait until both tasks are completed, whether an exception is thrown or not. Therefore, after a wait of about two seconds, Task.WhenAll is completed, and the exception is caught with the catch statement. However, you will only see the exception information from the first task that is passed to the WhenAll method. It's not the task that threw the exception first (which is the second task), but the first task in the list:


private async static void StartTwoTasksParallel()
{
try
{
Task t1 = ThrowAfter(2000, "first");
Task t2 = ThrowAfter(1000, "second");
await Task.WhenAll(t1, t2);
}
catch (Exception ex)
{
// just display the exception information of the first task
// that is awaited within WhenAll
Console.WriteLine("handled {0}", ex.Message);
}
}

One way to get the exception information from all tasks is to declare the task variables t1 and t2 outside of the try block, so they can be accessed from within the catch block. Here you can check the status of the task to determine whether they are in a faulted state with the IsFaulted property. In case of an exception, the IsFaulted property returns true. The exception information itself can be accessed by using Exception.InnerException of the Task class. Another, and usually better, way to retrieve exception information from all tasks is demonstrated next.

Using AggregateException Information

To get the exception information from all failing tasks, the result from Task.WhenAll can be written to a Task variable. This task is then awaited until all tasks are completed. Otherwise the exception would still be missed. As described in the last section, with the catch statement just the exception of the first task can be retrieved. However, now you have access to the Exception property of the outer task. The Exception property is of type AggregateException. This exception type defines the property InnerExceptions (not only InnerException), which contains a list of all the exceptions from the awaited for. Now you can easily iterate through all the exceptions:


private static async void ShowAggregatedException()
{
Task taskResult = null;
try
{
Task t1 = ThrowAfter(2000, "first");
Task t2 = ThrowAfter(1000, "second");
await (taskResult = Task.WhenAll(t1, t2));
}
catch (Exception ex)
{
Console.WriteLine("handled {0}", ex.Message);
foreach (var ex1 in taskResult.Exception.InnerExceptions)
{
Console.WriteLine("inner exception {0}", ex1.Message);
}
}
}

异步编程错误处理 ERROR HANDLING的更多相关文章

  1. [译]Javascript中的错误信息处理(Error handling)

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  2. 转:C++编程隐蔽错误:error C2533: 构造函数不能有返回类型

    C++编程隐蔽错误:error C2533: 构造函数不能有返回类型 今天在编写类的时候,出现的错误. 提示一个类的构造函数不能够有返回类型.在cpp文件里,该构造函数定义处并没有返回类型.在头文件里 ...

  3. 19 Error handling and Go go语言错误处理

    Error handling and Go go语言错误处理 12 July 2011 Introduction If you have written any Go code you have pr ...

  4. .NET中的异步编程——常见的错误和最佳实践

    在这篇文章中,我们将通过使用异步编程的一些最常见的错误来给你们一些参考. 背景 在之前的文章<.NET中的异步编程——动机和单元测试>中,我们开始分析.NET世界中的异步编程.在那篇文章中 ...

  5. C#学习笔记四(LINQ,错误和异常,异步编程,反射元数据和动态编程)

    LINQ 1.使用类似的数据库语言来操作集合? 错误和异常 异步编程 1.异步和线程的区别: 多线程和异步操作两者都可以达到避免调用线程阻塞的目的.但是,多线程和异步操作还是有一些区别的.而这些区别造 ...

  6. 基于任务的异步编程模式(TAP)的错误处理

    在前面讲到了<基于任务的异步编程模式(TAP)>,但是如果调用异步方法,没有等待,那么调用异步方法的线程中使用传统的try/catch块是不能捕获到异步方法中的异常.因为在异步方法执行出现 ...

  7. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions

    The ideal time to catch an error is at compile time, before you even try to run the program. However ...

  8. 说一说javascript的异步编程

    众所周知javascript是单线程的,它的设计之初是为浏览器设计的GUI编程语言,GUI编程的特性之一是保证UI线程一定不能阻塞,否则体验不佳,甚至界面卡死. 所谓的单线程就是一次只能完成一个任务, ...

  9. 探索Javascript异步编程

    异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变得明显.许多不同的方法都可以解决这个问题,本文讨论了一些方法 ...

随机推荐

  1. 一份快速实用的 tcpdump 命令参考手册

    对于 tcpdump 的使用,大部分管理员会分成两类.有一类管理员,他们熟知  tcpdump 和其中的所有标记:另一类管理员,他们仅了解基本的使用方法,剩下事情都要借助参考手册才能完成.出现这种情况 ...

  2. 关于db访问层的封装设计感想 dbpy项目的开发

    dbpy dbpy是一个python写的数据库CURD人性化api库.借鉴了 webpy db 和 drupal database 的设计. 如果喜欢 tornado db 或者 webpy db这类 ...

  3. mybatis自动映射和手动映射

    一对一查询 第一种方法: <!-- 查询所有订单信息 --> <select id="findOrdersList" resultType="cn.it ...

  4. https://www.cnblogs.com/freeflying/p/9950374.html

    https://www.cnblogs.com/freeflying/p/9950374.html

  5. zoj 1383 Binary Numbers

    Binary Numbers Time Limit: 2 Seconds      Memory Limit: 65536 KB Given a positive integer n, print o ...

  6. C 题 KMP中next[]问题

    题目大意: 找到能够进行字符串匹配的前缀 这题只要一直求next,直到next为0停止,记得答案是总长减去next的长度 #include <iostream> #include < ...

  7. 【贪心】codeforces D. Minimum number of steps

    http://codeforces.com/contest/805/problem/D [思路] 要使最后的字符串不出现ab字样,贪心的从后面开始更换ab为bba,并且字符串以"abbbb. ...

  8. 【贪心+博弈】C. Naming Company

    http://codeforces.com/contest/794/problem/C 题意:A,B两人各有长度为n的字符串,轮流向空字符串C中放字母,A尽可能让字符串字典序小,B尽可能让字符串字典序 ...

  9. vscode安装插件

    十分简单,知道名字叫啥后,直接搜索,安装,就完了,还可以查看自己已经安装了哪些插件. step1 如图.png step2 image.png step 3 去网上查找想要安装的插件的名字 step ...

  10. msp430项目编程03

    msp430中项目---液晶12864显示 1.液晶12864工作原理 2.电路原理说明 3.代码(静态显示) 4.代码(动态显示) 5.项目总结 msp430项目编程 msp430入门学习