码迷,mamicode.com
首页 > 其他好文 > 详细

异步编程错误处理 ERROR HANDLING

时间:2015-01-27 07:02:41      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

 

技术分享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

标签:

原文地址:http://www.cnblogs.com/hellohongfu/p/4251815.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!