Not awaitable method exception thowing inconsistent behaviour

一个人想着一个人 提交于 2020-05-16 22:32:47

问题


So I read on async/await and somewhere, someplace I read that if you don't await an async method you basically lose it. It fires and forgets and goes into the AEeher and if it throws an exception - you will never know.
This was the example the author used:

    static async void OnButtonClick()
    {
        yolo();
        string imageUrl = null;
        try
        {
            DownloadAndBlur(imageUrl);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Exception: {ex}");
        }
        Console.WriteLine("Done!");
    }

    static async Task DownloadAndBlur(string url)
    {
        if (url == null)
        {
            throw new ArgumentNullException(nameof(url));
        }
    }

Indeed, if I call the OnButtonClick() method from my code no exception gets thrown, or rather, nothing about an exception is printed on the console. While if I await the DownloadAndBlur method - an exception is written to the console.

So I tried to replicate the behaviour and wrote this:

    static async void Execute()
    {
        Console.WriteLine(1);
        yolo();
        Console.WriteLine(2);
    }

    static Task yolo()
    {
        throw new Exception();
    }

But an exception is thrown and my debugging session catches it. So what is different, because I think they are the same.


回答1:


The Execute method is not fire-and-forget. It is async void.

static async void Execute()
{
    YoloAsync();
}

Exceptions in async void methods are thrown in the current SynchronizationContext (or in the ThreadPool if the SynchronizationContext.Current is null), which normally results to the crashing of the process (source code).

Next, the YoloAsync method is not marked with the async modifier.

static Task YoloAsync()
{
    throw new Exception();
}

Semantically it is an asynchronous method since it returns a Task, but the task is not generated from an async-state-machine. So the code inside the YoloAsync method is executed synchronously like any other method, and unlike the async-state-machine-generated methods that propagate their exceptions through the Task they return.




回答2:


Maxim 26. "Fire and Forget" is fine, provided you never actually forget.

Getting a Exception in Multitasking is always difficulty.

If you are doing Mutlthreading, it is actually trivially easy to loose all exceptions by default. The thread itself swallows all Exceptions. This is the worst case that has to be handeled.

As a result, Multitasking approaches always catch all exceptions, then expose them in the Result. Task has a property for that. So Does RunWorkerCompletedEventArgs.

One job of the continuation code, is to check for and re-raise any Exceptions. It is something Task has to do for Multithreading support, even if it does not nessearily make sense with mere Multitasking.



来源:https://stackoverflow.com/questions/61689900/not-awaitable-method-exception-thowing-inconsistent-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!