C# Async Await 注意事項

Avoid Using Async Void  --- 避免使用async void

  • async void 只能用於事件處理函數。而且保證永遠不在用戶代碼中調用這些事件處理函數。
  • async void 調用時,不能使用await,因此程序執行不會中止在調用處,而是立刻執行下面的語句,可能會引發意外的狀況發生。
  • 在寫被用戶代碼調用的函數時,永遠使用async Task<T>、async Task返回值類型的函數。
  • await func() 容許編譯器把函數在await處拆分紅兩部分。第一個部分在await調用處結束。第二部分使用await調用的結果(若是有返回值的話),而後從哪裏開始執行。要使await關鍵詞,函數的返回類型必須是Task類型。

Beware of Deadlocks --- 當心死鎖

在某種程度上,異步方法具備傳染行爲。當要調用一個異步方法的時候,你必須讓調用異步方法的方法也變成異步形式。這種形式一直重複,直到向上移動到call stack的頂端,也就是事件處理函數。app

若是這個路徑中的某一個函數沒法變成異步方式,這將引入一個問題。舉例來講:constructors,他們不能是異步的。因此你不能在它的函數體中使用await。這時,有兩個處理方式,一個是把要調用的函數變爲async void形式,可是正如上一節所說的,這將讓咱們沒有辦法再await這個方法。另外一種方式是咱們經過調用返回的Task的Wait()函數,或者讀它的Result屬性,來同步的等待函數執行完成。固然,同步的代碼會暫時中止應用處理消息隊列,這是咱們最初使用異步函數所要解決的問題,這在大多數狀況下是壞主意。更糟糕的,在某些狀況下,這將形成死鎖。less

Any synchronously called asynchronous code in InnocentLookingClass constructor is enough to cause a deadlock:異步

public class InnocentLookingClass()
{
     public InnocentLookingClass()
     {
         DoSomeLengthyStuffAsync().Wait();
         // do some more stuff
     }
 
     private async Task DoSomeLengthyStuffAsync()
     {
         await SomeOtherLengthyStuffAsync();
     }
 
     // other class members
}

Let us dissect what is happening in this code.async

MyEventHandler synchronously calls InnocentLookingClass constructor, which invokesDoSomeLengthyStuffAsync, which in turn asynchronously invokes SomeOtherLengthyStuffAsync. The execution of the latter method starts; at the same time the main thread blocks at Wait untilDoSomeLengthyStuffAsync completes without giving control back to the main message loop.函數

Eventually SomeOtherLengthyStuffAsync completes and posts a message to the message queue implying that the execution of DoSomeLengthyStuffAsync can continue. Unfortunately, the main thread is waiting for that method to complete instead of processing the messages, and will therefore never trigger it to continue, hence waiting indefinitely.oop

As you can see, synchronously invoking asynchronous methods can quickly have undesired consequences. Avoid it at all costs; unless you are sure what you are doing, i.e. you are not blocking the main message loop.post

Allow Continuation on a Different Thread --- 容許在另外一個線程中繼續

在返回的Task對象上調用ConfigureAwait(false);ui

這個方法能夠避免死鎖,儘管它沒有辦法解決【在異步調用完成以前阻塞消息循環】的問題。this

 

 

 

 

 

from http://www.dotnetcurry.com/csharp/1307/async-await-asynchronous-programming-examplesspa

相關文章
相關標籤/搜索