async (справочник по C#)
Модификатор async
позволяет указать, что метод, лямбда-выражение или анонимный метод является асинхронным. Если этот модификатор используется в методе или выражении, они называются асинхронными методами. Ниже приводится пример асинхронного метода с именем ExampleMethodAsync
:
public async Task<int> ExampleMethodAsync()
{
//...
}
Если вы только начали заниматься асинхронным программированием или не понимаете, как в асинхронном методе используется оператор await
для выполнения потенциально долгих операций без блокировки потока вызывающего объекта, ознакомьтесь с общими сведениями в статье Асинхронное программирование с использованием ключевых слов async и await. Следующий код размещается внутри асинхронного метода и вызывает метод HttpClient.GetStringAsync:
string contents = await httpClient.GetStringAsync(requestUrl);
Асинхронный метод выполняется синхронным образом до тех пор, пока не будет достигнуто первое выражение await
, после чего метод приостанавливается, пока не будет завершена ожидаемая задача. В то же время управление возвращается в вызывающий объект метода, как показано в примере в следующем разделе.
Если метод, который изменяется ключевым словом async
, не содержит выражения или оператора await
, метод выполняется синхронно. Компилятор выводит предупреждения обо всех асинхронных методах, не содержащих операторы await
, поскольку такая ситуация может указывать на ошибку. См. раздел Предупреждение компилятора (уровень 1) CS4014.
Ключевое слово async
— это контекстно-зависимо ключевое слово, которое является ключевым словом, когда оно изменяет метод, лямбда-выражение или анонимный метод. Во всех других контекстах он интерпретируется как идентификатор.
Пример
В следующем примере показана структура и поток управления между обработчиком асинхронных событий StartButton_Click
и асинхронным методом ExampleMethodAsync
. В результате выполнения этого асинхронного метода возвращается число символов на веб-странице. Код подходит для приложения Windows Presentation Foundation (WPF) или приложения для Магазина Windows Presentation Foundation (WPF), которые создаются в Visual Studio; см. комментарии к коду для настройки приложения.
Этот код можно выполнить в Visual Studio как приложение Windows Presentation Foundation (WPF) или приложение Магазина Windows. Вам понадобятся элементы управления типа "Кнопка" (StartButton
) и "Текстовое поле" (ResultsTextBox
). Не забудьте задать имена и обработчик, чтобы получить код следующего вида:
<Button Content="Button" HorizontalAlignment="Left" Margin="88,77,0,0" VerticalAlignment="Top" Width="75"
Click="StartButton_Click" Name="StartButton"/>
<TextBox HorizontalAlignment="Left" Height="137" Margin="88,140,0,0" TextWrapping="Wrap"
Text="<Enter a URL>" VerticalAlignment="Top" Width="310" Name="ResultsTextBox"/>
Выполнение кода в виде приложения WPF:
- Вставьте этот код в класс
MainWindow
в MainWindow.xaml.cs. - Добавьте ссылку на System.Net.Http.
- Добавьте директиву
using
для System.Net.Http.
Выполнение кода в виде приложения Магазина Windows:
- Вставьте этот код в класс
MainPage
в MainPage.xaml.cs. - Добавьте
using
директивы для System.Net.Http и System.Threading.Tasks.
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
// ExampleMethodAsync returns a Task<int>, which means that the method
// eventually produces an int result. However, ExampleMethodAsync returns
// the Task<int> value as soon as it reaches an await.
ResultsTextBox.Text += "\n";
try
{
int length = await ExampleMethodAsync();
// Note that you could put "await ExampleMethodAsync()" in the next line where
// "length" is, but due to when '+=' fetches the value of ResultsTextBox, you
// would not see the global side effect of ExampleMethodAsync setting the text.
ResultsTextBox.Text += String.Format("Length: {0:N0}\n", length);
}
catch (Exception)
{
// Process the exception if one occurs.
}
}
public async Task<int> ExampleMethodAsync()
{
var httpClient = new HttpClient();
int exampleInt = (await httpClient.GetStringAsync("http://msdn.microsoft.com")).Length;
ResultsTextBox.Text += "Preparing to finish ExampleMethodAsync.\n";
// After the following return statement, any method that's awaiting
// ExampleMethodAsync (in this case, StartButton_Click) can get the
// integer result.
return exampleInt;
}
// The example displays the following output:
// Preparing to finish ExampleMethodAsync.
// Length: 53292
Внимание
Дополнительные сведения о задачах и коде, который выполняется во время ожидания задачи, см. в разделе Асинхронное программирование с использованием ключевых слов async и await. Полный пример консоли, в котором используются похожие элементы, см. в разделе Обработка асинхронных задач по мере их завершения (C#).
Типы возвращаемых данных
Асинхронные методы могут иметь следующие типы возвращаемых значений:
- Task
- Task<TResult>
- void. Методы
async void
обычно рекомендуются для кода, отличного от обработчиков событий, поскольку вызывающие объекты не могутawait
эти методы и должны реализовать другой механизм уведомления об успешном завершении или ошибках. - Любой тип, имеющий доступный
GetAwaiter
метод. Одной из таких реализаций является типSystem.Threading.Tasks.ValueTask<TResult>
. Доступ к нему осуществляется посредством пакета NuGetSystem.Threading.Tasks.Extensions
.
Асинхронный метод не может объявлять параметры in, ref или out, а также иметь ссылочное возвращаемое значение, но он может вызывать методы с такими параметрами.
Task<TResult>
указывается в качестве возвращаемого типа асинхронного метода, если оператор return метода задает операнд типа TResult
. Класс Task
используется при отсутствии содержательного значения, возвращаемого методом при его завершении. То есть вызов метода возвращает Task
, однако когда Task
завершен, любое выражение await
, которое ожидает Task
, возвращает значение void
.
Возвращаемый тип void
используется в основном для определения обработчиков событий, которые требуют этого возвращаемого типа. Вызывающий объект асинхронного метода, возвращающего void
, не может ожидать его и перехватывать создаваемые методом исключения.
Вы возвращаете другой тип, как правило, тип значения, который имеет GetAwaiter
метод для минимизации выделения памяти в критически важных для производительности разделах кода.
Дополнительные сведения и примеры см. в разделе Асинхронные типы возвращаемых значений.