在某種程度上,異步方法具備傳染行爲。當要調用一個異步方法的時候,你必須讓調用異步方法的方法也變成異步形式。這種形式一直重複,直到向上移動到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
在返回的Task對象上調用ConfigureAwait(false);ui
這個方法能夠避免死鎖,儘管它沒有辦法解決【在異步調用完成以前阻塞消息循環】的問題。this
from http://www.dotnetcurry.com/csharp/1307/async-await-asynchronous-programming-examplesspa