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


async (справочник по C#)

Модификатор async позволяет указать, что метод, лямбда-выражение или анонимный метод является асинхронным. При использовании этого модификатора в методе или выражении создается асинхронный метод. Ниже приводится пример асинхронного метода с именем ExampleMethodAsync:

public async Task<int> ExampleMethodAsync()
{
    //...
}

Справочные документы по языку C# описывают последнюю выпущенную версию языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.

Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.

Подсказка

Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей об истории версий языка C#.

Если вы не знакомы с асинхронным программированием или не понимаете, как асинхронный метод использует await оператор для выполнения потенциально длительной работы без блокировки потока вызывающего объекта, ознакомьтесь с введением в асинхронное программирование с асинхронным и ожидаемым. Следующий код размещается внутри асинхронного метода и вызывает метод HttpClient.GetStringAsync:

string contents = await httpClient.GetStringAsync(requestUrl);

Асинхронный метод выполняется синхронно, пока не достигнет первого await выражения. На этом этапе метод приостанавливается до завершения ожидаемой задачи. В то же время управление возвращается в вызывающий объект метода, как показано в примере в следующем разделе.

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

Ключевое async слово является контекстным. Это ключевое слово, только если оно изменяет метод, лямбда-выражение или анонимный метод. Во всех других контекстах компилятор интерпретирует его как идентификатор.

В следующем примере показана структура и поток управления между обработчиком асинхронных событий StartButton_Click и асинхронным методом ExampleMethodAsync. В результате выполнения этого асинхронного метода возвращается число символов на веб-странице. Код подходит для приложения Windows Presentation Foundation (WPF) или приложения Магазина Windows, создаваемого в 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="&lt;Enter a URL&gt;" 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>. Он доступен, добавив пакет System.Threading.Tasks.ExtensionsNuGet.

Асинхронный метод не может объявлять какие-либо inrefref readonlyпараметры или out параметры, а также не может иметь возвращаемое значение ссылки. Однако он может вызывать методы, имеющие такие параметры.

Укажите Task<TResult> в качестве возвращаемого типа асинхронного метода, если оператор return метода задает операнду типа TResult. Используйте, Task если метод не возвращает понятное значение при завершении. То есть вызов метода возвращает Task, однако когда Task завершен, любое выражение await, которое ожидает Task, возвращает значение void. Используйте возвращаемый void тип в основном для определения обработчиков событий, для которых требуется этот тип возвращаемого значения. Вызывающий объект асинхронного метода, возвращающего void, не может ожидать его и перехватывать создаваемые методом исключения. Возвращает другой тип, как правило, тип значения, который имеет GetAwaiter метод для минимизации выделения памяти в критически важных разделах кода.

Дополнительные сведения и примеры см. в разделе Асинхронные типы возвращаемых значений.

См. также