Поделиться через


Оператор 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#.

См. также