2017-10-10 93 views
3

說我有方法,像這樣:在異步函數中,爲什麼我必須等待?

private async Task SomeMethod() 
{ 
    await DoSomethingAsync(); 
    await DoSomethingElseAsync(); 
    return; 
} 

鑑於DoSomethingElseAsync返回Task它似乎像你應該能夠做到這一點:

private async Task SomeMethod() 
{ 
    await DoSomethingAsync(); 
    return DoSomethingElseAsync(); 
} 

但編譯器抱怨這一點:

由於'SomeMethod'是返回'Task'的異步方法,因此返回關鍵字不得後面跟着一個對象表達式。你打算返回'Task<T>'嗎?

這是爲什麼?

+4

@YvetteColomb它不是* this *問題的確切副本。 OP不詢問何時使用await。這問''爲什麼我不能返回任務?' –

+0

@YvetteColomb這不是重複的,你所指的問題是什麼時候使用await,這個問是爲什麼第二個方法不能簡單地返回而不是寫await,我認爲英語非常明確地認定這兩者是不同的。 –

+4

在第一個'await DoSomethingAsync();'完成之前 - 方法已經返回給調用者(畢竟它是異步方法)。所以在'await'之後你無法返回特定的值 - 調用者此時已經收到一個返回值並向前移動。 – Evk

回答

5

它很像yield returnreturn的工作原理。對於迭代器你有這些方法之一

public IEnumerable<int> SomeIterator() 
{ 
    for(int I = 0; I < 10; I++) yield return I; 
} 

public IEnumerable<int> SomeIterator() 
{ 
    return Enumerable.Range(0, 10); // return result of another iterator. 
} 

但你不能有兩個。它不起作用,因爲迭代器要麼被編譯器轉換爲類,要麼用yield來處理懶惰的迭代,要麼就像其他返回其他東西的普通方法一樣。

public IEnumerable<int> SomeIterator() // not valid 
{ 
    for(int I = 0; I < 10; I++) yield return I; 
    return Enumerable.Range(0, 10); 
} 

故事是相同的約returnasync/await。對於返回類型爲Task的方法,您可以返回Task或使用async/await

Task<T>,如果你使用等待你必須返回T但由於該方法被編譯成狀態機將無法返回Task<T>,則方法必須返回T。 (對於Task方法無效)

如果您不使用async/await方法將與其他常規方法完全相同。

+0

這與Evk的評論結合起來很有意義。 雖然我仍然覺得有點dissapointing'等待Thing1();等待Thing2();返回'和'等待Thing1();返回Thing2();'不要簡單地編譯成相同的代碼,因爲它仍然是合乎邏輯的(至少在我的腦海裏!) – DJL

-2

你應該這樣做

private async Task<SomeReturnType> SomeMethod() 
{ 
    return await DoSomethingElseAsync(); 
} 

或者你可以做

private async Task<SomeReturnType> SomeMethod() 
{ 
    SomeReturnType someResult = await DoSomethingAsync(); 
    return someResult; 
} 

您需要指定其鍵入您的任務回報。 而你必須等待異步任務。

+0

這就是OP的嘗試,並沒有工作 –

+0

也許嘗試返回一個任務。 – Neuxz

+0

請閱讀問題和錯誤信息。你不能*從異步**方法**返回任何東西**。 '異步任務'是一種方法,而不是一種功能。 –

0

當您使用await - 控制流可能會離開當前的方法並返回給調用者。假設DoSomethingAsync是一些長時間運行的操作。您致電SomeMethodDoSomethingAsync任務已啓動,但您不能等待它在該方法內完成 - 否則沒有任何內容會成爲「異步」。所以控制流程離開Method並且應該向呼叫者提供返回值。返回值是在完成整個SomeMethod時完成的任務。它可以完成有或沒有結果(TaskTask<T>返回值)。出於這個原因,你await後返回的內容不能是SomeMethod返回類型 - 它只能是結果型T(如果SomeMethod返回的任務),或者只是簡單的return指示的SomeMethod完成,如果返回簡單Task

0

在通常的方法中,return的意思是「從方法中返回該值,如果有的話」。在async方法中,return的含義更改爲「將返回的Task的結果設置爲該值(如果有)」。

但你不能將二者結合起來:在async Task方法,你不能直接return一個Task。其中一個原因是,如果您使用await版本,則該方法實際上已經返回Task,並且無法返回另一個。

當談到回國,async Task方法的行爲就像一個void方法,因爲它僅允許return;,但從來沒有return value;