No history yet

Введение в асинхронность

Основы асинхронности

Представьте себе повара на кухне. Синхронный повар поставит воду кипятиться и будет стоять, глядя на кастрюлю, пока она не закипит. Только после этого он начнет резать овощи. Это неэффективно.

Асинхронный повар поставит воду, а пока она греется, займется нарезкой овощей. Он не блокирует себя ожиданием, а выполняет другую работу. Когда вода закипит, он вернется к ней. Именно так работает асинхронное программирование.

В программировании «ожидание» часто связано с операциями ввода-вывода (I/O): сетевыми запросами, чтением файла с диска или обращением к базе данных. Эти операции могут быть медленными. Если основной поток приложения будет их ждать, пользовательский интерфейс «зависнет», а сервер не сможет обрабатывать другие запросы. Асинхронность решает эту проблему, позволяя приложению оставаться отзывчивым.

Основная цель асинхронности — избежать блокировки потоков и эффективно использовать ресурсы во время ожидания завершения I/O-операций.

Ключевые слова: async и await

В C# асинхронность реализуется с помощью двух ключевых слов: async и await.

async

other

Модификатор, который указывается в сигнатуре метода. Он сообщает компилятору, что метод является асинхронным и может содержать одно или несколько выражений await.

await

other

Оператор, применяемый к задаче (Task) внутри асинхронного метода. Он приостанавливает выполнение метода до тех пор, пока ожидаемая задача не завершится, но при этом не блокирует поток, а возвращает управление вызывающему коду.

Когда выполнение доходит до оператора await, происходит несколько вещей:

  1. Метод, содержащий await, приостанавливается.
  2. Управление возвращается коду, который вызвал этот метод.
  3. Поток, в котором выполнялся метод, освобождается и может заняться другой работой.
  4. Когда асинхронная операция (например, сетевой запрос) завершается, выполнение метода возобновляется с того места, где оно было приостановлено.
Lesson image

Работа с классом Task

В основе асинхронной модели в .NET лежит класс Task и его обобщенная версия Task<TResult>. Эти классы представляют собой обещание выполнить некоторую работу и, возможно, вернуть результат в будущем.

Task представляет операцию, которая не возвращает значения (аналог void). Task<TResult> представляет операцию, которая возвращает значение типа TResult.

Метод, помеченный как async, должен возвращать один из трех типов:

  • Task: для асинхронных операций без возвращаемого значения.
  • Task<TResult>: для асинхронных операций с возвращаемым значением.
  • void: следует использовать только для обработчиков событий (например, Button_Click). Использование async void в других случаях считается плохой практикой, так как такие методы сложно тестировать и обрабатывать в них исключения.
// Асинхронный метод, который ничего не возвращает
public async Task SaveDataAsync(string data)
{
    // Имитация асинхронной записи в файл
    await Task.Delay(1000); 
    Console.WriteLine("Data saved.");
}

// Асинхронный метод, возвращающий строку
public async Task<string> FetchWebsiteContentAsync(string url)
{
    using (var client = new HttpClient())
    {
        // Ожидаем завершения GET-запроса и получаем результат
        string content = await client.GetStringAsync(url);
        return content;
    }
}

// Пример вызова
public async Task RunExample()
{
    Console.WriteLine("Starting fetch...");
    string result = await FetchWebsiteContentAsync("https://example.com");
    Console.WriteLine($"Fetch completed. Content length: {result.Length}");
    await SaveDataAsync(result);
}

В этом примере FetchWebsiteContentAsync немедленно возвращает Task<string>, который представляет собой обещание получить содержимое сайта. Оператор await затем приостанавливает выполнение RunExample, пока GetStringAsync не завершится и не вернет результат. После этого результат присваивается переменной content, и выполнение продолжается.

Quiz Questions 1/4

Какое основное преимущество использования асинхронного программирования в приложении с пользовательским интерфейсом?

Quiz Questions 2/4

Какой тип должен возвращать асинхронный метод (async), который выполняет операцию, но не возвращает никакого значения?

Асинхронное программирование — мощный инструмент для создания производительных и отзывчивых приложений. Понимание async, await и Task является ключевым навыком для современного C#-разработчика.