Оператор await — асинхронно ожидает завершения задачи
Оператор await
приостанавливает вычисление включающего асинхронного метода до завершения асинхронной операции, представленной его операндом. После завершения асинхронной операции оператор await
возвращает результат операции, если таковой имеется. Когда оператор await
применяется к операнду, который представляет уже завершенную операцию, он возвращает результат операции немедленно без приостановки включающего метода. Оператор await
не блокирует поток, который вычисляет асинхронный метод. Когда оператор await
приостанавливает включающий метод async, элемент управления возвращается вызывающему объекту метода.
В следующем примере метод HttpClient.GetByteArrayAsync возвращает экземпляр Task<byte[]>
, который представляет асинхронную операцию, создающую массив байтов после завершения. До завершения операции оператор await
приостанавливает метод DownloadDocsMainPageAsync
. Когда DownloadDocsMainPageAsync
приостанавливается, управление возвращается методу Main
, который является вызывающим объектом DownloadDocsMainPageAsync
. Метод Main
выполняется до тех пор, пока ему не потребуется результат асинхронной операции, выполняемой методом DownloadDocsMainPageAsync
. Когда GetByteArrayAsync получает все байты, вычисляется остальная часть метода DownloadDocsMainPageAsync
. После этого вычисляется остальная часть метода Main
.
public class AwaitOperator
{
public static async Task Main()
{
Task<int> downloading = DownloadDocsMainPageAsync();
Console.WriteLine($"{nameof(Main)}: Launched downloading.");
int bytesLoaded = await downloading;
Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
}
private static async Task<int> DownloadDocsMainPageAsync()
{
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");
var client = new HttpClient();
byte[] content = await client.GetByteArrayAsync("https://learn.microsoft.com/en-us/");
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
return content.Length;
}
}
// Output similar to:
// DownloadDocsMainPageAsync: About to start downloading.
// Main: Launched downloading.
// DownloadDocsMainPageAsync: Finished downloading.
// Main: Downloaded 27700 bytes.
Операнды await
выражения должны предоставлять уведомления при завершении задачи. Как правило, делегат вызывается при завершении задачи либо успешно, либо неудачно. В await
разделе спецификации языка C# приведены сведения о реализации этих уведомлений.
В предыдущем примере используется асинхронный Main
метод. Дополнительные сведения см. в описании оператора await в методе Main.
Примечание.
Общие сведения об асинхронном программировании см. в разделе Асинхронное программирование с использованием ключевых слов async и await. Асинхронное программирование async
и await
следует асинхронной модели, основанной на задачах.
Оператор await
можно использовать только в методе, лямбда-выражении или в анонимном методе, изменяемом ключевым словом async. В асинхронном методе оператор нельзя использовать await
в теле синхронной локальной функции, внутри блока инструкции блокировки и в небезопасном контексте.
Операнд оператора await
обычно имеет один из следующих типов .NET: Task, Task<TResult>, ValueTask или ValueTask<TResult>. Однако любое ожидаемое выражение может быть операндом оператора await
. Дополнительные сведения см. в разделе об ожидаемых выражениях в спецификации языка C#.
Тип выражения await t
является TResult
, если тип выражения t
является Task<TResult> или ValueTask<TResult>. Если тип t
является Task или ValueTask, тип await t
является void
. В обоих случаях, если t
вызывает исключение, await t
воспроизводит это исключение.
Асинхронные потоки и освобождаемые объекты
Вы можете использовать инструкцию await foreach
для работы с асинхронным потоком данных. Дополнительные сведения см. в foreach
разделе инструкций инструкции инструкций итерации.
Инструкция await using
используется для работы с асинхронно освобождаемым объектом, то есть с объектом типа, который реализует интерфейс IAsyncDisposable. Дополнительные сведения см. в разделе Использование асинхронных освобождаемых объектов статьи Реализация метода DisposeAsync.
Оператор await в методе Main
МетодMain
, являющийся точкой входа приложения, может возвращать Task
или Task<int>
включать асинхронный режим, чтобы можно было использовать await
оператор в тексте. В более ранних версиях C#, чтобы убедиться, что метод Main
ожидает завершения асинхронной операции, можно получить значение свойства Task<TResult>.Result экземпляра Task<TResult>, возвращаемого соответствующим асинхронным методом. Для асинхронных операций, которые не создают значение, можно вызвать метод Task.Wait. См. сведения о том, как выбрать версию языка в описании версий C#.
Спецификация языка C#
Дополнительные сведения см. в разделе об ожидаемых выражениях в спецификации языка C#.