2017-03-17 49 views
1

我剛剛被介紹給這個概念,所以如果答案是微不足道的道歉。如果每個異步都有等待,並且每個等待都應用於異步,那麼在哪裏以及如何結束?

據我所知,async只是一個標誌,說在方法內部有一個await,控制將在異步方法正在工作時返回給調用者。我的理解是,假設調用堆棧中的某個地方沒有等待異步方法,而不是至少立即(即在異步方法執行時完成其他一些工作),這是有用的。

但是,await似乎只適用於async方法,其中內部必須有await s。這創建了一個連續的呼叫鏈。它必須在某個地方結束,等待被應用到非異步方法。但是哪裏?

+0

您無法等待非異步方法,但可以通過訪問任務的Result屬性來等待異步方法完成工作。你可以用它來「切斷」異步鏈,或者你可以讓整個鏈是異步鏈。 –

+0

@TamásSzabó - 是的,你可以。你可以'等待'返回* awaitable *對象的任何方法。 「任務」恰好是最常見的等待。但即使在那裏,也沒有要求'Task'返回方法是'async'。儘管它看起來是方法簽名的一部分,但它實際上完全是您所調用方法的一個實現細節。 –

+0

猜猜我錯了。謝謝你清理那個! –

回答

2

但是,await似乎只適用於異步方法,而異步方法又必須在內部等待。

從技術上講,await不適用於方法。該方法被調用並返回某些內容(例如,Task),然後await應用到該任務

因此,誤解在這裏:await適用於等待(例如,任務),而不是方法。

它必須在某個地方結束,等待被應用到非異步方法。

是。任何方法都可以返回Task(或任何等待),無論是否爲async。方法可以使用來構造它的任務(並且大部分方法我們這樣寫),但它也可以直接構建一個。通常,低級異步方法使用TaskFactory.FromAsyncTaskCompletionSource<T>來創建它們返回的任務。

0

它結束於您正在使用的最高層並且您不想阻止的層。假設你有一個Winforms應用程序。這裏的所有方法都會在某些情況下結束,這將成爲異步鏈的結束。

例如:

private async Task DoSomethingAsync() 
{ 
    await DbClass.GetSomeItemsFromDbAsync(); 
} 

public partial class MyForm : Form 
{ 
    private async void btButton_Click(object sender, EventArgs e) 
    { 
     await DoSomethingAsync(); 
    } 
} 

如果你能看到的例子,我們有一個方法是異步。此方法在按鈕的Click事件中調用。所以Event-Listener被標記爲async,但不能從其他任何地方調用。在這裏,你離開你的鏈條,並達到終點。表單不會阻止,這就是我們想要實現的。

如果您在GUI上思考所有方法將最終發生在事件中,因爲整個程序都是事件驅動的。在控制檯應用程序中,端點將是主要方法。在那裏你不會將返回類型從void更改爲Task,這會阻止你的異步鏈,因爲無法等待void。

我希望這可以幫助你瞭解鏈條。

+0

在Windows窗體中使用'async void'是否正常? – mukh1n

+0

@ mukh1n在Event-Listener上使用它:是,因爲這是您的端點。應該避免在「正常」方法中使用它,因爲以後不能等待。 – Sebi

+0

我實際上是在詢問最低級別(請參閱Stephen的答案)。但是你的觀點也是一個很好的觀點:高層的人不得不等待,至少不會立即,因爲整個事情都是有意義的。 – lfk