異步(1) async & await
阿新 • • 發佈:2017-12-31
通知 表達式 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"; }); }
- 進入主線程開始執行
- 調用async方法,返回一個Task,註意這個時候另外一個線程已經開始運行,也就是GetName裏面的 Task 已經開始工作了
- 主線程繼續往下走
- 第3步和第4步是同時進行的,主線程並沒有掛起等待
- 如果另一個線程已經執行完畢,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