MCP

вторник, 24 декабря 2013 г.

Забавности с async/await

Тут решил в одном проекте таки заюзать это чудо, вещь, конечно, забавная, но мозг выворачивает наизнанку. Обычное асинхронное программирование после этого кажется абсолютно простым и очевидным.
В качестве выворота мозга приведу простой пример (он упрощён до предела, в реальности, конечно, всё было сложнее):

public static void Process()
{
try
{
DoSomething();
}
catch (Exception)
{
}
}

public static async void DoSomething()
{
throw new Exception();
}

Итак, есть метод Process, который ловит все исключения и обрабатывает их, и метод DoSomething, который в процессе своей работы может кинуть эксепшен.
Как думаете, что будет в результате выполнения данного кода (вызова метода Process)?

Подумали? Теперь правильный ответ. Будет необработанный эксепшен и аварийное завершение приложения. Бздынь! Размещаем метод DoSomething где-нибудь подальше и наслаждаемся неожиданными крешами приложения в самый неожиданный момент.

Вот это один из примеров разрыва шаблонов. Чтобы такого не повторилось DoSomething должен возвращать не void а человеческий Task, после этого, чтобы избавиться от предупреждения о некорректном поведении в методе Process надо написать await DoSomething, а чтобы скомпилировалось к Process добавить async. И вот только после этого всё будет работать как и ожидалось.

Приятного кодинга 

4 комментария:

  1. Не понятно к чемуЭто ты решил написать про такой пример. Ну да, такое возможно. Значит ли, что такой код стоит писать? Конечно нет. http://msdn.microsoft.com/en-us/library/hh524395.aspx#BKMK_VoidReturnType то

    ОтветитьУдалить
  2. К тому, что поведение слишком неочевидное и нелогичное, хоть и описано в документации. Fire and forget и невозможность перехватить эксепшены вообще не вяжется. С тасками уже подобное делали, и переделали, когда до использования дошло http://force-net.com/2013/06/task.html

    ОтветитьУдалить
  3. На сколько я помню - этот код выдаст тебе compilation warning :) Не логично будет игнорировать warnings. async и await - это просто кодогенерация. Никакого волшебства. Так к этому и стоит относиться.

    ОтветитьУдалить
  4. Это очень хитрая кодогенерация, которая по факту меняет весь твой код. И её надо бы хорошо понимать, чтобы не нарваться на проблему. Варнинг тут, кстати, только на лишний async в DoSomething, но это из-за слишком упрощённого примера.

    ОтветитьУдалить