1. 程式人生 > >異步(1) async & await

異步(1) async & await

通知 表達式 mar div calling 創建 我們 相對 client

1 什麽是異步

異步的另外一種含義是計算機多線程的異步處理。與同步處理相對,異步處理不用阻塞當前線程來等待處理完成,而是允許後續操作,直至其它線程將處理完成,並回調通知此線程。

2 異步場景

  • l 不涉及共享資源,或對共享資源只讀,即非互斥操作
  • l 沒有時序上的嚴格關系
  • l 不需要原子操作,或可以通過其他方式控制原子性
  • l 常用於IO操作等耗時操作,因為比較影響客戶體驗和使用性能
  • l 不影響主線程邏輯

3 異步編寫 C#

Async await關鍵字

Async method

三種返回類型

– void (public async void InvokeAsync();) (應僅用於事件處理程序)

– Task (pubic async Task InvokeAsync();)

– Task<T> (public async Task<string> InvokeAsync();)

await 不會開啟新的線程,當前線程會一直往下走直到遇到真正的Async方法(比如說HttpClient.GetStringAsync),這個方法的內部會用Task.Run或者Task.Factory.StartNew 去開啟線程。也就是如果方法不是.NET為我們提供的Async方法,我們需要自己創建Task,才會真正的去創建線程

static void Main(string[] args)
        {
            Console.WriteLine("Main Thread Id: {0}\r\n", Thread.CurrentThread.ManagedThreadId);
            Test();
            Console.ReadLine();
        }

        static async Task Test()
        {
            Console.WriteLine("Before calling GetName, Thread Id: {0}\r\n
", Thread.CurrentThread.ManagedThreadId); var name = GetName(); //我們這裏沒有用 await,所以下面的代碼可以繼續執行 // 但是如果上面是 await GetName(),下面的代碼就不會立即執行,輸出結果就不一樣了。 Console.WriteLine("End calling GetName.\r\n"); Console.WriteLine("Get result from GetName: {0}", await name); } static async Task<string> GetName() { // 這裏還是主線程 Console.WriteLine("Before calling Task.Run, current thread Id is: {0}", Thread.CurrentThread.ManagedThreadId); return await Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("‘GetName‘ Thread Id: {0}", Thread.CurrentThread.ManagedThreadId); return "Jesse"; }); }

技術分享圖片

  1. 進入主線程開始執行
  2. 調用async方法,返回一個Task,註意這個時候另外一個線程已經開始運行,也就是GetName裏面的 Task 已經開始工作了
  3. 主線程繼續往下走
  4. 第3步和第4步是同時進行的,主線程並沒有掛起等待
  5. 如果另一個線程已經執行完畢,name.IsCompleted=true,主線程仍然不用掛起,直接拿結果就可以了。如果另一個線程還同有執行完畢, name.IsCompleted=false,那麽主線程會掛起等待,直到返回結果為止。

使用註意:

  • 異步代碼使用 Task<T> 和 Task,它們是對後臺所完成的工作進行建模的構造。
  • async 關鍵字將方法轉換為異步方法,這使你能在其正文中使用 await 關鍵字。
  • 應用 await 關鍵字後,它將掛起調用方法,並將控制權返還給調用方,直到等待的任務完成。
  • 僅允許在異步方法中使用 await。
  • async 方法需在其主體中具有 await 關鍵字,否則它們將永不暫停!
  • 應將“Async”作為後綴添加到所編寫的每個異步方法名稱中。

  • await 語句 (await Task)
Task task = client.SendMailAsync(mailMessage);

await task;

await 表達式

Task<byte[]> task = webClient.DownloadDataTaskAsync(uri);

byte[] result = await task;

OR

byte[] result = await webClient.DownloadDataTaskAsync(uri);

部分內容引用來自

http://www.cnblogs.com/jesse2013/p/async-and-await.html

異步(1) async & await