Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 295 296 297 298 299 300 301 302 303 ... 642

await Task.WhenAny(task1, task2, task3);

В результате вывод становится таким:

Fun With Async ===>

Done with work!

Void method completed

Done with second task!

Completed

Done with third task!

Done with first task!

Вызов асинхронных методов из неасинхронных методов

В каждом из предшествующих примеров ключевое слово async использовалось для возвращения в поток вызывающего кода, пока выполняется асинхронный метод. В целом ключевое слово await может применяться только в методе, помеченном как async. А что если вы не можете (или не хотите) помечать метод с помощью async?

К счастью, существуют другие способы вызова асинхронных методов. Если вы просто не используете ключевое слово await, тогда код продолжает работу после асинхронного метода, не возвращая управление вызывающему коду. Если вам необходимо ожидать завершения асинхронного метода (что происходит, когда применяется ключевое слово await), то существуют два подхода.

Первый подход предусматривает просто использование свойства Result с методами, возвращающими Task<T>, или метода Wait() с методами, возвращающими Task/Task<T>. (Вспомните, что метод, который возвращает значение, обязан возвращать Task<T>, будучи асинхронным, а метод, не имеющий возвращаемого значения, возвращает Task, когда является асинхронным.) Если метод терпит неудачу, то возвращается AggregateException.

Можете также добавить вызов GetAwaiter().GetResult(), который обеспечивает такой же эффект, как ключевое слово await в асинхронном методе, и распространяет исключения в той же манере, что и async/await. Тем не менее, указанные методы помечены в документации как "не предназначенные для внешнего использования", а это значит, что они могут измениться либо вовсе исчезнуть в какой-то момент в будущем. Вызов GetAwaiter().GetResult() работает как с методами, возвращающими значение, так и с методами без возвращаемого значения.

На заметку! Решение использовать свойство Result или вызов GetAwaiter().GetResult() с Task<T> возлагается полностью на вас, и большинство разработчиков принимают решение, основываясь на обработке исключений. Если ваш метод возвращает Task, тогда вы должны применять вызов GetAwaiter().GetResult() или Wait().

Например, вот как вы могли бы вызывать метод DoWorkAsync():

Console.WriteLine(<b>DoWorkAsync().Result</b>);

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

Console.WriteLine(<b>DoWorkAsync().GetAwaiter().GetResult()</b>);

Чтобы остановить выполнение до тех пор, пока не произойдет возврат из метода с возвращаемым типом void, просто вызовите метод Wait() на объекте Task:

MethodReturningVoidAsync().Wait();

Ожидание с помощью await в блоках catch и finally

 В версии C# 6 появилась возможность помещения вызовов await в блоки catch и finally. Для этого сам метод обязан быть async. Указанная возможность демонстрируется в следующем примере кода:

static async Task&lt;string&gt; MethodWithTryCatch()

{

  try

  {

    //Do some work

    return &quot;Hello&quot;;

  }

  catch (Exception ex)

  {

    await LogTheErrors();

    throw;

  }

  finally

  {

    await DoMagicCleanUp();

  }

}

Обобщенные возвращаемые типы в асинхронных методах (нововведение в версии 7.0)

До выхода версии C# 7 возвращаемыми типами методов async были только Task, Task&lt;T&gt; и void. В версии C# 7 доступны дополнительные возвращаемые типы при условии, что они следуют шаблону с ключевым словом async. В качестве конкретного примера можно назвать тип ValueTask. Введите код, подобный показанному ниже:

static async ValueTask&lt;int&gt; ReturnAnInt()

{

  await Task.Delay(1_000);

  return 5;

}

К типу ValueTask применимы все те же самые правила, что и к типу Task, поскольку ValueTask — это просто объект Task для типов значений, заменяющий собой принудительное размещение объекта в куче.

Локальные функции (нововведение в версии 7.0)

Локальные функции были представлены в главе 4 и использовались в главе 8 с итераторами. Они также могут оказаться полезными для асинхронных методов. Чтобы продемонстрировать преимущество, сначала нужно взглянуть на проблему. Добавьте новый метод по имени MethodWithProblems() со следующим кодом:

1 ... 295 296 297 298 299 300 301 302 303 ... 642
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю бесплатно.
Похожие на Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю книги

Оставить комментарий