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):


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

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:


  1. private static void DontHandle()
  2. {
  3. try
  4. {
  5. ThrowAfter(200, "first");
  6. // exception is not caught because this method is finished
  7. // before the exception is thrown
  8. }
  9. catch (Exception ex)
  10. {
  11. Console.WriteLine(ex.Message);
  12. }
  13. }
  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:


  1. private static async void HandleOneError()
  2. {
  3. try
  4. {
  5. await ThrowAfter(2000, "first");
  6. }
  7. catch (Exception ex)
  8. {
  9. Console.WriteLine("handled {0}", ex.Message);
  10. }
  11. }

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:


  1. private static async void StartTwoTasks()
  2. {
  3. try
  4. {
  5. await ThrowAfter(2000, "first");
  6. await ThrowAfter(1000, "second"); // the second call is not invoked
  7. // because the first method throws
  8. // an exception
  9. }
  10. catch (Exception ex)
  11. {
  12. Console.WriteLine("handled {0}", ex.Message);
  13. }
  14. }

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:


  1. private async static void StartTwoTasksParallel()
  2. {
  3. try
  4. {
  5. Task t1 = ThrowAfter(2000, "first");
  6. Task t2 = ThrowAfter(1000, "second");
  7. await Task.WhenAll(t1, t2);
  8. }
  9. catch (Exception ex)
  10. {
  11. // just display the exception information of the first task
  12. // that is awaited within WhenAll
  13. Console.WriteLine("handled {0}", ex.Message);
  14. }
  15. }

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:


  1. private static async void ShowAggregatedException()
  2. {
  3. Task taskResult = null;
  4. try
  5. {
  6. Task t1 = ThrowAfter(2000, "first");
  7. Task t2 = ThrowAfter(1000, "second");
  8. await (taskResult = Task.WhenAll(t1, t2));
  9. }
  10. catch (Exception ex)
  11. {
  12. Console.WriteLine("handled {0}", ex.Message);
  13. foreach (var ex1 in taskResult.Exception.InnerExceptions)
  14. {
  15. Console.WriteLine("inner exception {0}", ex1.Message);
  16. }
  17. }
  18. }

异步编程错误处理 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. [第一波模拟\day1\T2]{分班}(divide.cpp)

    [题目描述] 小N,小A,小T又大了一岁了. 现在,他们已经是高二年级的学生了.众所周知,高二的小朋友是要进行文理科分班考试的,这样子的话,三个好朋友说不定就会不分在一个班. 于是三个人决定,都考平均 ...

  2. ES6(函数新增特性)

    ES6(函数新增特性) 1.函数参数默认值 没有 y 时,默认就是world 有 y 时,输出值即可 (错误) (C有默认值,正确) 默认值后面不能再有没有默认值的变量 2.作用域 y 取其前面的 x ...

  3. BeautifulSoup实例

    Beautiful Soup 4.4.0 中文文档:http://beautifulsoup.readthedocs.io/zh_CN/latest/ #coding:utf-8from bs4 im ...

  4. URI跟URL的区别

    关于URL和URI的区别,个人见解.    初学java,最近被一个概念搞得头晕脑胀,就是url和uri的概念和区别,网上查了一大通,发现各种回答眼花缭乱,有百科直接粘贴的,有胡说八道的,有故意绕来绕 ...

  5. 如何安装python包

    安装python包有两种方法: 使用Python包管理器pip工具 在Linux系统中,首先 yum install python-pip 然后就可以欢快的pip install *** 啦 源代码安 ...

  6. python020 Python3 OS 文件/目录方法

    os 模块提供了非常丰富的方法用来处理文件和目录.常用的方法如下表所示: 序号 方法及描述 1 os.access(path, mode) 检验权限模式 2 os.chdir(path) 改变当前工作 ...

  7. Codeforces Round #277 (Div. 2 Only)

    A:SwapSort http://codeforces.com/problemset/problem/489/A 题目大意:将一个序列排序,可以交换任意两个数字,但要求交换的次数不超过n,输出任意一 ...

  8. 【BFS+优先级队列】Rescue

    https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/I [题意] 给定一个n*m的迷宫,A的多个小伙伴R要去营救A,问需要时间最少的小 ...

  9. 前端学习之-- Jquery

    Jquery学习笔记 中文参考文档:http://jquery.cuishifeng.cn Jquery是一个包含DOM/BOM/JavaScript的类库引入jquery文件方法:<scrip ...

  10. centos、mac的grafana安装和简单使用

    1.安装: 参考官方文档安装说明:https://grafana.com/grafana/download Redhat & Centos(64 Bit): wget https://s3-u ...