2021-05-12 14:32:11
C#非同步方法返回void與Task的區別詳解
C#非同步方法返回void和Task的區別
如果非同步(async關鍵字)方法有返回值,返回型別為T時,返回型別必然是 Task<T>。
但是如果沒有返回值,非同步方法的返回型別有2種,一個是返回 Task, 一個是返回 void:
public async Task CountDownAsync(int count) { for (int i = count; i >= 0; i--) { await Task.Delay(1000); } } public async void CountDown(int count) { for (int i = count; i >= 0; i--) { await Task.Delay(1000); } }
呼叫時,如果返回 Task, 但返回值被忽略時,VS 會用綠色波浪線警告:
CountDownAsync(3); ~~~~~~~~~~~~~~~~~
資訊為:
(awaitable) Task AsyncExample.CountDownAsync(int count)
Usage:
await CountDownAsync(...);Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
中文為:
CS4014:由於此呼叫不會等待,因此在此呼叫完成之前將會繼續執行當前方法。請考慮將"await"運運算元應用於呼叫結果。
新增 await 後就正常了:
await CountDownAsync(3);
如果呼叫者不是一個非同步方法,因為只有在非同步方法中才可以使用 await,
或者並不想在此等待,如想同時執行多個 CountDownAsync(),
就不能應用 await 來消除警告。
此時可以改用 void 返回值的版本:
void Test() { ... CountDown(3); CountDown(3); ... } async void CountDown(int count) { for (int i = count; i >= 0; i--) { await Task.Delay(1000); } }
Never call async Task methods without also awaiting on the returned Task. If you don't want to wait for the async behaviour to complete, you should call an async void method instead.
摘自:http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/
CountDown() 可以直接呼叫 CountDownAsync() 實現:
async void CountDown(int count) { await CountDownAsync(count); }
使用下劃線變數忽略非同步方法的返回值也可以消除警告:
void Test() { ... _ = CountDownAsync(3); _ = CountDownAsync(3); ... }
但是這樣同時也會忽略 CountDownAsync() 中的異常。如以下異常會被忽略。
void Test() { ... _ = CountDownAsync(3); ... } async Task CountDownAsync(int count) { for (int i = count; i >= 0; i--) { await Task.Delay(1000); } throw new Exception(); }
如果是呼叫返回 void 的非同步方法,Unity 會報錯:
Exception: Exception of type 'System.Exception' was thrown.
對 Async 字尾的說明
You could say that the Async suffix convention is to communicate to the API user that the method is awaitable. For a method to be awaitable, it must return Task for a void, or Task<T> for a value-returning method, which means only the latter can be suffixed with Async.
摘自:https://stackoverflow.com/questions/15951774
grpc 生成的程式碼中,非同步請求返回了一個 AsyncCall 物件,AsyncCall 實現了 GetAwaiter() 介面:
public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, ...)
可以這樣呼叫並等待:
var resp = await client.GetFeatureAsync(req);
雖然返回型別不是Task<>, 但是可等待,所以新增了 Async 字尾。
總結
到此這篇關於C#非同步方法返回void與Task區別的文章就介紹到這了,更多相關C#非同步方法返回區別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章