zoukankan      html  css  js  c++  java
  • 任务并行库-处理任务中的异常

      注意:返回void的异常方法不会等待。这是因为从async void方法抛出的异常无法捕获,因此,异步方法最好返回一个Task类型。处理程序方法或者重写基类方法不受此规则限制。

      异步方法的异常较好的一个处理方式,就是使用await关键字,将其放在try/catch语句中。如下:

      

    public static async Task ThrowExcrptionAsync(int ms, string message)
            {
                await Task.Delay(ms);
                throw new Exception(message);
            }
    
     public static async Task Main(string[] args)
            {
                //以下语句不会捕捉到异常(方法已经执行完毕,而throw new Exception(message)这句话还没执行,所以上面这段代码并不会捕获到异常)
                try
                {
                   ThrowExcrptionAsync(2000, "first");
                }
                catch (Exception e)
                {
                   Console.WriteLine(e.Message);
                }
                Console.ReadKey();

          try { await ThrowExcrptionAsync(2000, "first"); } //使用await关键字捕捉异常
          catch (Exception e)
          {
            Console.WriteLine(e.Message); } Console.ReadKey();
          } }

      在任务中,处理异常和其它异步方式处理异常类似,如果能在所发生异常的线程中处理,那么不要在其它地方处理。但是对于一些不可预料的异常,那么可以通过几种方式来处理。

      可以通过访问task.Result属性来处理异常,因为访问这个属性的Get方法会使当前线程等待直到该任务完成,并将异常传播给当前线程,这样就可以通过try catch语句块来捕获异常。另外使用task.GetAwaiter().GetResult()方法和第使用task.Result类似,同样可以捕获异常。如果是要捕获多个任务中的异常错误,那么可以通过ContinueWith()方法来处理

    具体如何实现,演示代码如下所示。

    static void Main(string[] args)
    {
        Task<int> task;
        // 在主线程中调用 task.Result task中的异常信息会直接抛出到 主线程中
        try
        {
            task = Task.Run(() => TaskMethod("Task 1", 2));
            int result = task.Result;
            WriteLine($"结果为: {result}");
        }
        catch (Exception ex)
        {
            WriteLine($"异常被捕捉:{ex.Message}");
        }
        WriteLine("------------------------------------------------");
        WriteLine();
    
        // 同上 只是访问Result的方式不同
        try
        {
            task = Task.Run(() => TaskMethod("Task 2", 2));
            int result = task.GetAwaiter().GetResult();
            WriteLine($"结果为:{result}");
        }
        catch (Exception ex)
        {
            WriteLine($"异常被捕捉: {ex.Message}");
        }
        WriteLine("----------------------------------------------");
        WriteLine();
    
        var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
        var t2 = new Task<int>(() => TaskMethod("Task 4", 4));
    
        var complexTask = Task.WhenAll(t1, t2);
        // 通过ContinueWith TaskContinuationOptions.OnlyOnFaulted的方式 如果task出现异常 那么才会执行该方法
        var exceptionHandler = complexTask.ContinueWith(t => {
            WriteLine($"异常被捕捉:{t.Exception.Message}");
            foreach (var ex in t.Exception.InnerExceptions)
            {
                WriteLine($"-------------------------- {ex.Message}");
            }
        },TaskContinuationOptions.OnlyOnFaulted);
    
        t1.Start();
        t2.Start();
    
        ReadLine();
    }
    
    static int TaskMethod(string name, int seconds)
    {
        WriteLine($"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}");
    
        Sleep(TimeSpan.FromSeconds(seconds));
        // 人为抛出一个异常
        throw new Exception("Boom!");
        return 42 * seconds;
    }

     

  • 相关阅读:
    版本控制工具 svn 一
    测试用例 (一)
    Jmeter (四) 关联
    Jmeter (三) 集合点 、检查点 (断言)
    Jmeter (二) 参数化
    Jmeter (一) 安装
    自动化测试 selenium 测试软件安装
    postman 接口测试(一)
    PHP使用Redis的Pub/Sub(发布订阅)命令
    idea控制台乱码问题
  • 原文地址:https://www.cnblogs.com/gougou1981/p/12624514.html
Copyright © 2011-2022 走看看