Pull to refresh

Comments 8

Ага блинк без дэлэя и наступает счастье. Надо только следить, чтобы вызываемые участки кода были неблокирующие и в случае непредвиденного зависания разруливать ситуацию.
Например добавить вачдог на тиньке, который в проблемной ситуации будет перезапускать всю систему.

Есть одна проблема. Await блокирует вызывающий поток и весь смысл асинхронности теряется. Так что код который вы написали не асинхронный аж никак.

Await блокирует вызывающий поток

С какого перепугу? Вы часом не путаете оператор await и одноименный метод у интерфейса Condition?

Await блокирует вызывающий поток и весь смысл асинхронности теряется

await в C# не блокирует вызывающий поток.

Наверное, мои вопросы будут скорее к оригиналу, нежели к Вашему переводу. Но всё же.


  1. Отсутствует полный исходный код примеров. В частности, что в оригинале, что в переводе отсутствует код метода PassTheTime.


  2. Асинхронность в .net, к большому сожалению не настолько проста, как описывается в статье =(( Наверное, стоило бы в заключение дать ссылки либо на другие примеры использования, либо на более глубоко разбираемые примеры по async-await.



В приведенном примере синхронного кода если, например, внутри метода BakeCake() вывалится Exception — это прервет выполнение всех последующих методов.


А вот для асинхронного кода уже начинаются вариации. Похожий пример описан в блоге Stephen Cleary: https://blog.stephencleary.com/2016/12/eliding-async-await.html (раздел Exceptions).


Поясню на примере.


Пусть код метода BakeCakeAsync выглядит так:


public static async Task<bool> BakeCakeAsync(bool isPreheated)
{
  if (!isPreheated)
    throw new InvalidOperationException("before 1st await");
  var result = await InnerBakeCakeAsync(isPreheated).ConfigureAwait(false);
  if (isPreheated)
    throw new InvalidOperationException("after await");
  return result;
}

Так вот: если метод вызовется isPreheated = true, то исключение в основном методе "поймается" на строке


Task<bool> bakeCakeTask = BakeCakeAsync(isPreheated);

И AddFrostingIngredients не будет вызван.


А вот если вызвать BakeCakeAsync вызовется с isPreheated = false, то исключение "поймается" уже только на строке с await-ом:


bool isBaked = await bakeCakeTask;

И получается, что AddFrostingIngredients вполне себе успеет выполниться


То есть при определенных условиях мы подготовим замороженные ингредиенты к приготовлению не посмотрев даже, что с процессом выпекания что-то не так.

Так вот: если метод вызовется isPreheated = true, то исключение в основном методе "поймается" на строке Task<bool> bakeCakeTask = BakeCakeAsync(isPreheated); И AddFrostingIngredients не будет вызван.

Вы это проверяли? Насколько я знаю, в любом случае исключение будет "спрятано" в возвращаемый Task, независимо от положения относительно первого await.

Вы это проверяли?

Там все немного хитрее. Если BakeCakeAsyncasync, то обернется. А если нет, то есть вот так:


public static Task<bool> BakeCakeAsync(bool isPreheated)
{
  if (!isPreheated)
    throw new InvalidOperationException();
  return InnerBakeCakeAsync(isPreheated);
}

то не обернется. При этом преобразование одного в другое — частая вещь, когда люди не хотят лишних накладных расходов на стейт-машины, или, наоборот, когда код усложняется.


А со стороны вызывающего кода эти варианты имплементации и вовсе неотличимы, поэтому он должен быть готов, что эксепшн будет брошен как на вызове метода, так и на эвейте таска.

Sign up to leave a comment.

Articles