В этой статье я хотел бы представить свое понимание асинхронного программирования на C# и .Net.

Оглавление

  • Асинхронное программирование на C#
  • Основные моменты асинхронного программирования на C#
    1. Повышение производительности приложений
    2. Асинхронные методы на C# легко писать
    3. Ожидание появления множества асинхронных методов
    4. Отмена задачи
    5. Параллельное программирование
    6. Асинхронность и многопоточность
  • Заключение

Асинхронное программирование на C#

Сегодня во многих языках программирования поддержка асинхронного программирования стала довольно популярной. Асинхронное программирование на C# — то же самое.

Самый распространенный пример — общение с сервером через javascript Ajax. Это можно понять; асинхронное программирование — это возможность выполнять задачи независимо. Они не должны запускаться последовательно (могут работать параллельно) или один поток, не дожидаясь, пока другой повысит производительность приложения.

В C# выполнение начинается с метода Main и заканчивается, когда возвращается метод Main. При этом все процессы выполняются один за другим. Поток должен дождаться завершения предыдущего потока.

static void Main(string[] args)
{
    DoTaskOne();
    DoTaskTwo();
}

При синхронном программировании «DoTaskTwo» не может начаться, пока не завершится «DoTaskOne». В асинхронном программировании вызываемый метод запускается в фоновом режиме и вызов потока не блокируется. После вызова метода выполнения поток возвращается к вызову и выполнению других задач. Обычно они используют Thread или Task.

В нашем случае, если мы запустим «DoTaskOne» асинхронно, то после вызова «DoTaskOne» выполнение немедленно вернется к методу Main и запустит «DoTaskTwo».

Мы можем создавать потоки с помощью класса Thread или использовать асинхронные шаблоны, предоставляемые .Net, для выполнения асинхронного программирования.

Основные моменты асинхронного программирования на C#

1. Улучшить производительность приложений

Асинхронное программирование часто используется для блокировки бессознательных процессов, таких как доступ к веб-сайту, а доступ к ресурсам в Интернете иногда бывает медленным. Кроме того, есть несколько других процессов, которые должны быть построены асинхронно: работа с файлами, изображениями,…

Начиная с .Net Framework 4.5 и среды выполнения Windows, в API будет несколько методов, поддерживающих асинхронный режим, как показано ниже.

  • Веб-доступ: HttpClient, SyndicationClient
  • Работа с файлами: StorageFile, StreamWriter, StreamReader, XmlReader
  • Работа с изображениями: MediaCapture, BitmapEncoder, BitmapDecoder
  • Программирование WCF: Синхронные и асинхронные операции

2. Асинхронные методы на C# легко писать

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

Таким образом, .Net Framework 4.5 был создан с простым подходом, делающим асинхронное программирование более простым, чем когда-либо. Самая сложная вещь, которую когда-либо делал программист в прошлом, — это компилятор. Таким образом, логическая структура приложения останется привычной для синхронного программирования.

В C# ключевые слова async и await занимают центральное место в асинхронном программировании. Используя эти два ключевых слова, вы можете использовать ресурсы .Net или среды выполнения Windows для простого создания асинхронного метода. Давайте последуем примеру ниже:

async Task<int> AccessTheWebAsync()
{
    HttpClient client = new HttpClient();
    // GetStringAsync returns a Task<string>. That means that when you await the
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();
    //  - The await operator then retrieves the string result from getStringTask.
    string urlContents = await getStringTask;
    // The return statement specifies an integer result.
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
    return urlContents.Length;
}

Вызовите вышеуказанный метод:

string urlContents = await client.GetStringAsync();

На изображении ниже показано выполнение метода GetStringAsync:

3. Ожидание множества асинхронных методов

Во-первых, взгляните на следующий код:

private async void CallWithAsync()
{
    string result = await DoTask1Async("Task1");
    string result1 = await DoTask2Async("Task2");
    Console.WriteLine(result);
    Console.WriteLine(result1);
}

Выше мы ожидаем два асинхронных метода последовательно. Вызов второй функции начнется после завершения работы первой функции. На практике это не очень хорошая идея, если они не зависят от результатов друг друга, потому что «DoTask1Async» может заблокировать программу. Для решения этой задачи на C# мы можем использовать задачу.КогдаВсе

private async static void MultipleAsyncMethodsWithCombinators()
{
     Task<string> t1 = DoTask1Async("Task1");
     Task<string> t2 = DoTask2Async("Task2");
     await Task.WhenAll(t1, t2);
    Console.WriteLine("Finished both methods.n " +
    "Result 1: {0}n Result 2: {1}", t1.Result, t2.Result);
}

В приведенном выше коде оба вышеуказанных метода выполняются параллельно, не блокируя друг друга.

4. Отмена задачи

Раньше, если мы использовали Thread, его отмена была невозможна. .Net 4.0 и более поздние версии C # предоставляют способ отмены выполнения задач на основе класса CancellationTokenSource.

static void Main(string[] args)
{
    CallWithAsync();
    Console.ReadKey();
}
async static void CallWithAsync()
{
    try
    {
        CancellationTokenSource source = new CancellationTokenSource();
        source.CancelAfter(TimeSpan.FromSeconds(1));
        var t1 = await GreetingAsync("HiepHV", source.Token);
    }
    catch (OperationCanceledException ex)
    {
        Console.WriteLine(ex.Message);
    }
}
static Task<string> GreetingAsync(string name, CancellationToken token)
{
    return Task.Run<string>(() =>
    {
        return Greeting(name, token);
    });
}
static string Greeting(string name, CancellationToken token)
{
    Thread.Sleep(3000);
    token.ThrowIfCancellationRequested();
    return string.Format("Hello, {0}", name);
}

Это привлекательная функция в среде программирования .Net. В реальных приложениях есть такие вещи, как загрузка файлов, обработка документов и другие иммобилайзеры, которые иногда очень сложно отменить во время работы. Класс CancellationTokenSource может помочь нам легче контролировать это.

5. Параллельное программирование

Многие ПК и рабочие станции имеют два или четыре ядра ЦП, что позволяет одновременно выполнять несколько потоков.

В ближайшее время компьютерное оборудование будет все больше обновляться (с увеличением числа ядер ЦП, ..). Таким образом, чтобы воспользоваться преимуществами современного и будущего оборудования, вы можете распараллелить задачи в коде между несколькими обработчиками.

В прошлом параллельное программирование или многопоточность требовали низкоуровневого захвата потоков и блокировок. Появились VS 2010 и .Net 4.0, которые расширили поддержку параллельного программирования, предоставив новую среду выполнения, новые типы библиотек классов и новые инструменты диагностики. Эти функции предназначены для упрощения разработки параллельного программирования. На изображении ниже показана архитектура «параллельного программирования» в .Net 4.0:

Пример кода:

ParallelLoopResult result =
       Parallel.For(0, 100, async (int i) =>
       {
           Console.WriteLine("{0}, task: {1}, thread: {2}", i,
           Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
           await Task.Delay(10);
      });

Асинхронный и многопоточный

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

Сегодняшняя асинхронная технология в .Net позволяет выполнять несколько задач в одном и том же потоке или во многих разных потоках в зависимости от ситуации. Это значительное преимущество, которое лучше повышает производительность приложения по сравнению с использованием нескольких потоков.

Вывод

Большинство современных программистов хорошо знакомы с асинхронным программированием на разных языках, таких как javascript, java, python, ruby… В этой статье я хочу представить свое понимание программирования. Асинхронность в C# и .Net. Я надеюсь внести полезную перспективу для вас.