.Net 多線程 異步編程 Await、Async和Task

await和async簡介

  await和async是在C#5中引入,而且在.NetFramewor4.5以及.NetCore中進行了支持。主要是解決性能瓶頸,而且加強系統的響應能力。
圖片html

msdn關於await以及async運行機理的描述

以上demo詳細的描述了使用await時程序的運行機制,須要注意的如下幾點:c#

  • 第五步:執行完成後若是發現下一步還有await即設置了中斷點,此時命令會直接跳出此方法即執行6,換句話說,await表達式執行時暫停並不構成方法退出,只會致使 finally 代碼塊不運行
  • 第七步:當執行當getStringTask返回結果(第七步)及await等待方法執行完成開始執行後續操做時(8)此時的線程已經和第四步執行的線程不一樣編號了,可是此時4所在線程上下文中的AsyncLocal變量會被複制到await返回後的線程上下文中。詳細參照http://www.javashuo.com/article/p-dphefeqz-dw.html
  • async 和 await 關鍵字不會建立其餘線程。 由於異步方法不會在其自身線程上運行,所以它不須要多線程.

Task簡介

Task類的表示單個操做不會返回一個值,一般以異步方式執行Task對象是一種的中心思想基於任務的異步模式。首次引入.NET Framework 4 中。
Task能夠經過如下幾種方式開始執行:多線程

Task.Run(() =>
            {
                Console.WriteLine("無返回值委託");
            });
            Task.Run<int>(() =>
            {
                Console.WriteLine("帶返回值委託");
                return 1;
            });
            Task t = new Task(() =>
            {
                Console.WriteLine("聲明一個Task能夠後續經過t.run執行");
            });
            TaskFactory factory = new TaskFactory();
            factory.StartNew<int>(() =>
            {
                Console.WriteLine("經過TaskFactory執行");
                return 1;
            });
            Task t4 = new Task(() =>
            {
                Console.WriteLine("同步執行");
            });
            // 同步執行
            t4.RunSynchronously();

task的執行方式這裏很少作介紹,下面主要說下Task的異常處理。app

異步方法內部的異常處理

.Net中異步方法由 async修飾符標記,一般包含一個或多個await表達式或語句。await表達式將await運算符應用於 Task 或Task 。因爲在異步方法中一般會存在多個線程,而子線程中的異常信息不能自動的拋到主線程上,因此要想在主線程上得到子線程的異常信息,須要藉助於返回的task這個對象。如下爲 Msdn給出的一段示例代碼: 異步

public async Task DoSomethingAsync()
{
    Task<string> theTask = DelayAsync();

    try
    {
        string result = await theTask;
        Debug.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception Message: " + ex.Message);
    }
    Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
    Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
    if (theTask.Exception != null)
    {
        Debug.WriteLine("Task Exception Message: "
            + theTask.Exception.Message);
        Debug.WriteLine("Task Inner Exception Message: "
            + theTask.Exception.InnerException.Message);
    }
}

private async Task<string> DelayAsync()
{
    await Task.Delay(100);

    // Uncomment each of the following lines to
    // demonstrate exception handling.

    //throw new OperationCanceledException("canceled");
    //throw new Exception("Something happened.");
    return "Done";
}

// Output when no exception is thrown in the awaited method:
//   Result: Done
//   Task IsCanceled: False
//   Task IsFaulted:  False

// Output when an Exception is thrown in the awaited method:
//   Exception Message: Something happened.
//   Task IsCanceled: False
//   Task IsFaulted:  True
//   Task Exception Message: One or more errors occurred.
//   Task Inner Exception Message: Something happened.

// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
//   Exception Message: canceled
//   Task IsCanceled: True
//   Task IsFaulted:  False

對於異步線程的執行結果,最多有三種狀況async

  • 正常執行結束:能夠經過IsCompletedSuccessfully 屬性表示任務正常結束,併成功執行。特別說明:IsCompleted爲true只能表示執行完成,當任務處於三種最終狀態之一: RanToCompletion, Faulted,或Canceled。時他都爲true
  • 發生異常:發生異常時,能夠經過返回的task對象中的IsFaulted屬性判斷,爲true時表示發生異常,若是要獲取具體的異常信息,能夠經過如下如下方式獲取
task.Exception.InnerException.Message
  • 異步線程被取消:異步線程被取消時task中的IsCanceled屬性會被設置爲true
    瞭解取消任務能夠參考msdn示例:
using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      // Create a cancellation token and cancel it.
      var source1 = new CancellationTokenSource();
      var token1 = source1.Token;
      source1.Cancel();
      // Create a cancellation token for later cancellation.
      var source2 = new CancellationTokenSource();
      var token2 = source2.Token;
       
      // Create a series of tasks that will complete, be cancelled, 
      // timeout, or throw an exception.
      Task[] tasks = new Task[12];
      for (int i = 0; i < 12; i++)
      {
          switch (i % 4) 
          {
             // Task should run to completion.
             case 0:
                tasks[i] = Task.Run(() => Thread.Sleep(2000));
                break;
             // Task should be set to canceled state.
             case 1:   
                tasks[i] = Task.Run( () => Thread.Sleep(2000),
                         token1);
                break;         
             case 2:
                // Task should throw an exception.
                tasks[i] = Task.Run( () => { throw new NotSupportedException(); } );
                break;
             case 3:
                // Task should examine cancellation token.
                tasks[i] = Task.Run( () => { Thread.Sleep(2000); 
                                             if (token2.IsCancellationRequested)
                                                token2.ThrowIfCancellationRequested();
                                             Thread.Sleep(500); }, token2);   
                break;
          }
      }
      Thread.Sleep(250);
      source2.Cancel();
       
      try {
         Task.WaitAll(tasks);
      }
      catch (AggregateException ae) {
          Console.WriteLine("One or more exceptions occurred:");
          foreach (var ex in ae.InnerExceptions)
             Console.WriteLine("   {0}: {1}", ex.GetType().Name, ex.Message);
       }   

      Console.WriteLine("\nStatus of tasks:");
      foreach (var t in tasks) {
         Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status);
         if (t.Exception != null) {
            foreach (var ex in t.Exception.InnerExceptions)
               Console.WriteLine("      {0}: {1}", ex.GetType().Name,
                                 ex.Message);
         }
      }
   }
}
// The example displays output like the following:
//   One or more exceptions occurred:
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//      TaskCanceledException: A task was canceled.
//      NotSupportedException: Specified method is not supported.
//      TaskCanceledException: A task was canceled.
//   
//   Status of tasks:
//      Task #13: RanToCompletion
//      Task #1: Canceled
//      Task #3: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #8: Canceled
//      Task #14: RanToCompletion
//      Task #4: Canceled
//      Task #6: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #7: Canceled
//      Task #15: RanToCompletion
//      Task #9: Canceled
//      Task #11: Faulted
//         NotSupportedException: Specified method is not supported.
//      Task #12: Canceled
相關文章
相關標籤/搜索