День двести двенадцатый. #ЗаметкиНаПолях
Многопоточность.
9. Async/await. Начало
В C#5 введено понятие асинхронной функции. Это метод (анонимная функция) объявленный с модификатором async, который может использовать выражения await для ожидания операций. Если операция, которую ожидает выражение, ещё не завершена, асинхронная функция немедленно возвращает управление, а затем продолжается с того места, на котором остановилась, когда значение становится доступным (в соответствующем потоке). Естественный ход программы, при котором следующий оператор не выполняется, пока текущий оператор не завершится, сохраняется, но без блокировки потока. В примере ниже приложение Windows Forms извлекает текст из заданного URL и отображает длину HTML кода в элементе Label:
Если поместить точку останова на первую строку и выполнить код до неё в отладчике, стек вызовов покажет, что вы находитесь в событии
Если поместить точку останова после выражения await и снова запустить код, то (предполагая, что потребовалось использовать продолжение) в стеке вызовов больше не будет метода Button.OnClick. Этот метод давно завершился. Поначалу такое изменение стека вызовов может шокировать, но это необходимо для работы асинхронного кода. Работа асинхронных методов достигается компилятором путём создания сложного конечного автомата.
Продолжение следует…
Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.
Многопоточность.
9. Async/await. Начало
В C#5 введено понятие асинхронной функции. Это метод (анонимная функция) объявленный с модификатором async, который может использовать выражения await для ожидания операций. Если операция, которую ожидает выражение, ещё не завершена, асинхронная функция немедленно возвращает управление, а затем продолжается с того места, на котором остановилась, когда значение становится доступным (в соответствующем потоке). Естественный ход программы, при котором следующий оператор не выполняется, пока текущий оператор не завершится, сохраняется, но без блокировки потока. В примере ниже приложение Windows Forms извлекает текст из заданного URL и отображает длину HTML кода в элементе Label:
public class AsyncIntro : FormКраткую строку:
{
private static readonly HttpClient client = new HttpClient();
private readonly Label label;
private readonly Button button;
public AsyncIntro()
{
…
button.Click += DisplayWebSiteLength;
…
}
async void DisplayWebSiteLength(object sender, EventArgs e)
{
label.Text = "Fetching...";
string text = await client.GetStringAsync("http://csharpindepth.com");
label.Text = text.Length.ToString();
}
…
}
string text = await client.GetStringAsync("http://csharpindepth.com");можно написать подробнее:
Task<string> task = client.GetStringAsync("http://csharpindepth.com");Заметьте, что тип задачи -
string text = await task;
Task<string>
, но тип выражения await - просто string
. В этом смысле оператор await
выполняет операцию развёртывания (когда ожидаемое значение типа Task<TResult>
).Если поместить точку останова на первую строку и выполнить код до неё в отладчике, стек вызовов покажет, что вы находитесь в событии
Button.OnClick
. Когда вы достигаете await
, код проверяет, доступен ли результат, и, если это не так (в данном случае почти всегда), он планирует выполнение продолжения (continuation) после завершения операции. Продолжение – это фактически функция обратного вызова, которая выполняется, когда асинхронная операция завершена (аналогично методу ContinueWith
класса Task
). Продолжение поддерживает состояние метода (захватывает все доступные переменные), а также выполняется в том же потоке (в данном случае в потоке пользовательского интерфейса).Если поместить точку останова после выражения await и снова запустить код, то (предполагая, что потребовалось использовать продолжение) в стеке вызовов больше не будет метода Button.OnClick. Этот метод давно завершился. Поначалу такое изменение стека вызовов может шокировать, но это необходимо для работы асинхронного кода. Работа асинхронных методов достигается компилятором путём создания сложного конечного автомата.
Продолжение следует…
Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.