await (Справочник по C#)
Оператор await применяется к задаче в асинхронном методе, чтобы приостановить выполнение метода до тех пор, пока ожидаемая задача не будет завершена. Задача представляет выполняющуюся работу.
Асинхронный метод, в котором используется await, должен быть модифицирован ключевым словом async. Такой метод, определенный с помощью модификатора async и обычно содержащий одно или несколько выражений await, называется асинхронным методом или методом async.
Примечание
Ключевые слова async и await были введены в Visual Studio 2012.Введение в асинхронное программирование см. в разделе Асинхронное программирование с использованием ключевых слов Async и Await (C# и Visual Basic).
Задача, к которой применяется оператор await, обычно представляет собой возвращаемое значение из вызова метода, реализующего асинхронную модель на основе задач. Примеры включают значения типа Task или Task.
В следующем коде метод HttpClient GetByteArrayAsync возвращает Task<byte[]>, getContentsTask. Задача — это обещание создать фактический байтовый массив, когда задача будет завершена. Оператор await применяется к getContentsTask, чтобы приостановить выполнение в SumPageSizesAsync до тех пор, пока getContentsTask не будет завершен. Тем временем, управление возвращается к вызывающему объекту SumPageSizesAsync. После завершения метода getContentsTask, выражение await оценивается как массив байтов.
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
Важно!
Полный пример см. в разделе Пошаговое руководство. Получение доступа к Интернету с помощью модификатора Async и оператора Await (C# и Visual Basic).Можно загрузить пример со страницы Примеры кода разработчика на веб-сайте Майкрософт.Пример находится в проекте AsyncWalkthrough_HttpClient.
Как показано в предыдущем примере, если await применяется к результату вызова метода, который возвращает Task<TResult>, то тип выражения await — TResult. Если await применяется к результату вызова метода, который возвращает Task, то тип выражения await — void. В следующем примере показана разница.
// Keyword await used with a method that returns a Task<TResult>.
TResult result = await AsyncMethodThatReturnsTaskTResult();
// Keyword await used with a method that returns a Task.
await AsyncMethodThatReturnsTask();
Выражение await не блокирует поток, в котором он выполняется. Вместо этого он заставляет компилятор зарегистрировать остальную часть метода async как продолжение задачи awaited. Управление затем возвращается вызывающему объекту асинхронного метода. Если задача завершается, она вызывает его продолжение, а выполнение метода токена продолжится, где было остановлено.
Выражение await может произойти только в теле непосредственно внешнего метода, лямбда-выражения, или анонимного метода, помеченного модификатором async. Термин await (ожидать) служит как ключевое слово только в этом контексте. В другом месте, оно интерпретируется как идентификатор. В этом методе лямбда-выражение или анонимный метод, выражение await не может содержаться в теле синхронной функции, в выражении запроса, в блоке catch или finally выписка обработки исключений, в блоке выписка блокировки, либо в небезопасном контексте.
Исключения
Большинство асинхронных методов возвращают значение Task или Task. Свойства возвращаемой задачи содержат сведения о ее состоянии и истории, такие как завершена ли задача, привел ли асинхронный метод к исключению или был отменен, а также каков конечный результат. Оператор await получает доступ к этим свойствам.
Если выполняется await для возвращающего метода async, который вызывает исключение, оператор await повторно создает исключение.
Если выполняется await для возвращающего метода async, который отменен, оператор await повторно создает OperationCanceledException.
Одна задача в состоянии ошибки может отражать несколько исключений. Например, задача может быть результатом вызова Task.WhenAll. Когда ожидаете такой задачи, операция await повторно создает только одно из исключений. Однако невозможно предугадать, какое из исключений повторно создается.
Примеры обработки ошибок в асинхронных методах см. try-catch (Справочник по C#).
Пример
В следующем примере Windows Forms показано использование токена await в асинхронном методе WaitAsynchronouslyAsync. Сравните поведение этого метода с поведением WaitSynchronously. Без оператора await, примененного к задаче, WaitSynchronously выполняется одновременно несмотря на использование модификатора async в определении и вызов Thread.Sleep в своем теле.
private async void button1_Click(object sender, EventArgs e)
{
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();
// Call the method that runs synchronously.
//string result = await WaitSynchronously ();
// Display the result.
textBox1.Text += result;
}
// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
await Task.Delay(10000);
return "Finished";
}
// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
// Add a using directive for System.Threading.
Thread.Sleep(10000);
return "Finished";
}
См. также
Задачи
Ссылки
Основные понятия
Асинхронное программирование с использованием ключевых слов Async и Await (C# и Visual Basic)