Ver Fonte

Добавлена лекция с вопросами по асинхронному программированию в C#

u21-25tolstikov há 2 meses atrás
pai
commit
ac7f37a665
1 ficheiros alterados com 97 adições e 0 exclusões
  1. 97 0
      Лекции/CSharp/AsyncAwait

+ 97 - 0
Лекции/CSharp/AsyncAwait

@@ -0,0 +1,97 @@
+# Лекция: Асинхронное программирование в C#: Task, async/await и многопоточность
+## Введение
+Асинхронное программирование — это важная концепция в современных приложениях, позволяющая эффективно использовать ресурсы системы, особенно в задачах, связанных с вводом-выводом (I/O) или долгими вычислениями. В C# асинхронность реализуется с помощью ключевых слов async/await, а также классов Task и Task<T>. В этой лекции мы разберем, как работает асинхронное программирование, как избежать распространенных ошибок и как эффективно использовать многопоточность.
+
+## Основы асинхронного программирования
+Синхронный код выполняется последовательно, блокируя поток до завершения операции. Асинхронный код, напротив, позволяет выполнять операции без блокировки потока, что особенно полезно для I/O-операций, таких как чтение файлов, запросы к базам данных или API.
+
+Ключевые слова async и await являются основой асинхронного программирования в C#. Ключевое слово async указывает, что метод является асинхронным, а await приостанавливает выполнение метода до завершения задачи, не блокируя поток. Например:
+
+```
+public async Task<string> DownloadDataAsync(string url)
+{
+    using (HttpClient client = new HttpClient())
+    {
+        string result = await client.GetStringAsync(url);
+        return result;
+    }
+}
+```
+## Классы Task и Task<T>
+Класс Task представляет асинхронную операцию, которая может быть выполнена в фоновом режиме. Task<T> возвращает результат типа T после завершения задачи. Для создания и запуска задач можно использовать Task.Run, который позволяет выполнить код в отдельном потоке:
+
+```
+Task.Run(() => 
+{
+    // Долгая операция
+});
+```
+Для возврата результата без выполнения асинхронной операции можно использовать Task.FromResult:
+```
+public Task<int> CalculateAsync()
+{
+    return Task.FromResult(42);
+}
+```
+  
+Ожидание завершения задач осуществляется с помощью await. Использование Task.Wait() или Task.Result блокирует поток, что не рекомендуется в асинхронном коде.
+
+#Многопоточность и асинхронность
+Асинхронность не обязательно использует дополнительные потоки. Например, асинхронные I/O-операции могут выполняться без создания новых потоков. Многопоточность, напротив, предполагает использование нескольких потоков для параллельного выполнения задач.
+
+Пул потоков (ThreadPool) управляет потоками, которые используются для выполнения задач. Асинхронные методы могут использовать потоки из пула, но не всегда. Для параллельного выполнения задач можно использовать Task.WhenAll, который ожидает завершения нескольких задач:
+```
+Task<string> task1 = DownloadDataAsync("url1");
+Task<string> task2 = DownloadDataAsync("url2");
+
+string[] results = await Task.WhenAll(task1, task2);
+```
+Или Task.WhenAny, который ожидает завершения первой задачи:
+```
+Task<string> firstFinishedTask = await Task.WhenAny(task1, task2);
+```
+#Обработка ошибок в асинхронном коде
+Исключения в асинхронных методах сохраняются в задаче и выбрасываются при вызове await. Для обработки ошибок используется try/catch:
+```
+try
+{
+    await SomeAsyncMethod();
+}
+catch (Exception ex)
+{
+    Console.WriteLine($"Ошибка: {ex.Message}");
+}
+```
+  
+Для отмены асинхронных операций используется CancellationToken:
+```
+public async Task LongRunningOperationAsync(CancellationToken token)
+{
+    for (int i = 0; i < 10; i++)
+    {
+        token.ThrowIfCancellationRequested();
+        await Task.Delay(1000);
+    }
+}
+```
+## Лучшие практики асинхронного программирования
+Избегайте блокировки потоков. Не используйте Task.Result или Task.Wait() в асинхронном коде. Вместо этого используйте await для ожидания задач.
+
+Если контекст синхронизации не важен, используйте ConfigureAwait(false) для улучшения производительности:
+```
+await SomeAsyncMethod().ConfigureAwait(false);
+```
+Асинхронные методы не всегда требуют создания новых потоков. Используйте их для I/O-операций, чтобы минимизировать количество потоков.
+
+Избегайте использования async void. Вместо этого используйте async Task, чтобы избежать проблем с обработкой исключений.
+
+## Вопросы для самопроверки:
+1. В чем разница между синхронным и асинхронным кодом?
+
+2. Как работает ключевое слово await в асинхронных методах?
+
+3. Какие преимущества дает использование Task.WhenAll?
+
+4. Как обработать исключение в асинхронном методе?
+
+5. Для чего используется CancellationToken и как его применять?