[英]One line fire and forget: void vs. async void + await
我有一個void
事件處理程序,它只包含一行,它是對可await
方法的調用。
void Handler( object sender, EventArgs args ) => AwaitableMethod();
將返回類型更改為Task
不是一種選擇,因此無論語法糖如何,它都是一勞永逸的。 即便如此,Visual Studio 在 un await
ed 調用下放置了一個綠色波浪線,建議我使處理程序async void
並await
調用。
async void Handler( object sender, EventArgs args ) => await AwaitableMethod();
我的理解是,在這種情況下添加async void
和await
只是無用的開銷。 Visual Studio 是否知道一些我不知道的東西,或者只是不必要地煩人?
我的理解是,在這種情況下添加 async void 和 await 只是無用的開銷。
不。
如果Handler
返回一個Task
,那么這將是正確的,並且省略async
/ await
就可以了; 沒有async
/ await
的代碼只會直接返回Task
,而不是用await
“解包”它,然后用async
將它“包裝”回Task
。
然而,這里的情況並非如此。 Handler
程序返回void
,因此沒有async
/ await
的代碼將忽略返回的Task
,這在絕大多數情況下是錯誤的(因此編譯器警告)。 具體來說,忽略Task
將忽略來自該Task
任何異常。 您的代碼也不可能知道被忽略的Task
何時完成,但大概這是可以接受的,因為您的處理程序正在返回void
。
async void
方法有一個“注冊”,以便框架知道有任務仍在進行中,因此框架知道何時可以安全關閉。 .NET 提供的唯一真正關心這一點的框架是 ASP.NET pre-Core; 所有其他 .NET 提供的框架(包括所有 UI 框架)都會忽略該“注冊”。
在這種特殊情況下,它主要取決於您的錯誤處理。
如果AwaitableMethod
異步拋出,它將在第二個版本的 UI 線程上拋出。
我建議在這種情況下避免使用事件處理程序,並盡可能使用類似的方法。
public class Eventful
{
private readonly List<Func<Task>> _handlers = new List<Func<Task>>();
public void AddHandler(Func<Task> handler) => _handlers.Add(handler);
private async Task RunHandlers()
{
foreach (var handler in _handlers)
{
await handler();
}
}
}
public class Consumer
{
public Consumer()
{
var eventful = new Eventful();
eventful.AddHandler(async () =>
{
await DoAsyncTask();
});
}
private static async Task DoAsyncTask()
{
await Task.CompletedTask;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.