Есть ли у вас опыт работы с многопоточностью в .NET?

«Есть ли у вас опыт работы с многопоточностью в .NET?» — вопрос из категории Многопоточность, который задают на 32% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, есть практический опыт работы с многопоточностью и асинхронным программированием в .NET. Понимаю разницу между Thread, ThreadPool, Task и конструкциями async/await. Основной фокус — на написании эффективного и безопасного параллельного кода.

1. Асинхронное программирование (async/await) для I/O-bound операций: Используется для операций, связанных с ожиданием (сеть, файловая система, БД), чтобы не блокировать поток.

public async Task<string> DownloadDataAsync(string url)
{
    using var httpClient = new HttpClient();
    // Поток освобождается во время выполнения сетевого запроса
    var response = await httpClient.GetAsync(url).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}

2. Параллельная обработка данных (Parallel, PLINQ) для CPU-bound операций: Используется для распараллеливания вычислений, загружающих процессор.

var data = Enumerable.Range(1, 10000).ToList();
var results = new ConcurrentBag<int>();

Parallel.ForEach(data, item =>
{
    // Тяжёлое вычисление
    var processedItem = ExpensiveCalculation(item);
    results.Add(processedItem);
});

3. Синхронизация и потокобезопасность:

  • Для простых сценариев: Использование lock или потокобезопасных коллекций из System.Collections.Concurrent.
    
    private readonly object _syncLock = new object();
    private int _sharedCounter;

public void SafeIncrement() { lock (_syncLock) { _sharedCounter++; } } // Альтернатива: Interlocked.Increment(ref _sharedCounter);


*   **Для более сложных сценариев:** Использование `SemaphoreSlim`, `ManualResetEventSlim`, `ReaderWriterLockSlim` или `Channel` для producer/consumer.

**Основные проблемы и их решение:**
*   **Race Condition:** Решается корректной синхронизацией доступа к общим данным.
*   **Deadlock:** Избегается путём установления строгого порядка захвата блокировок (lock ordering) и использования таймаутов.
*   **Состязание за ресурсы (Contention):** Минимизируется за счёт уменьшения времени удержания блокировок и использования lock-free структур, где это возможно.