Не ожидаемое исключение метода из-за несогласованного поведения - PullRequest
1 голос
/ 09 мая 2020

Итак, я читал об async / await и где-то, где-то я читал, что если вы не ждете метода asyn c, вы в основном его потеряете. Он срабатывает, забывает и переходит в AEeher, и если он выдает исключение - вы никогда не узнаете. Автор использовал следующий пример:

    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));
        }
    }

Действительно, если я вызываю метод OnButtonClick() из моего кода, исключение не генерируется, или, скорее, ничего об исключении не выводится на консоль. Если я жду метода DownloadAndBlur - в консоль записывается исключение.

Итак, я попытался воспроизвести поведение и написал следующее:

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

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

Но возникает исключение и мой сеанс отладки улавливает это. Так что же другое, потому что я думаю, что они такие же.

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Метод Execute - это не метод «пустил и забыл». Это async void.

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

Исключения в методах async void выбрасываются в текущем SynchronizationContext (или в ThreadPool, если SynchronizationContext.Current имеет значение null), что обычно приводит к сбою процесса ( исходный код ).

Далее, метод YoloAsync не помечен * 1020 Модификатор *.

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

Семантически это асинхронный метод, поскольку он возвращает Task, но задача не создается из asyn c -state- машина. Таким образом, код внутри метода YoloAsync выполняется синхронно, как и любой другой метод, и в отличие от методов, генерируемых машиной asyn c -state, которые распространяют свои исключения через Task, которые они возвращают.

0 голосов
/ 09 мая 2020

Максим 26. «Сожгите и забудьте» - это нормально, если вы никогда не забудете.

Получить исключение в многозадачности всегда сложно.

Если вы используете Mutlthreading, на самом деле тривиально легко потерять все исключения по умолчанию. Сам поток поглощает все исключения. Это наихудший случай, с которым нужно справиться.

В результате подходы многозадачности всегда перехватывают все исключения, а затем отображают их в Результате. Задача имеет свойство для этого . Так делает RunWorkerCompletedEventArgs .

Одна из задач кода продолжения - проверять и повторно вызывать любые исключения. Это то, что Task должен делать для поддержки многопоточности, даже если это не обязательно имеет смысл с простой многозадачностью.

...