簡體   English   中英

一行即發即忘:void vs. async void + await

[英]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 voidawait調用。

async void Handler( object sender, EventArgs args ) => await AwaitableMethod();

我的理解是,在這種情況下添加async voidawait只是無用的開銷。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM