Найти в Дзене

1.2. Потоки в .NET (Managed Threads)

В .NET среда выполнения (CLR) разделяет потоки на два фундаментальных типа: Thread workerThread = new Thread(DoWork);
workerThread.IsBackground = true; // Фоновый режим
workerThread.Start(); Создание и управление: // Создание абстракции потока (нативный поток еще не создан)
Thread myThread = new Thread(WorkerMethod);
// Запуск нативного потока ОС
myThread.Start(argument);
// Ожидание завершения (блокирует текущий поток)
myThread.Join(TimeSpan.FromSeconds(5)); // С таймаутом Управление выполнением: Thread.Sleep(15); // Гарантированное переключение контекста (~15 мс)
Thread.Sleep(0); // Переключение на поток с равным/высшим приоритетом
Thread.Yield(); // Добровольная передача процессора (только текущее ядро)
Thread.SpinWait(100); // Активное ожидание без переключения контекста Устаревший подход (опасен!): // Прерывание в произвольной точке кода (Obsolete в .NET Core+)
thread.Abort();
// Прерывание только в точках ожидания
thread.Interrupt(); Современный подход че
Оглавление

1.2. Потоки в .NET (Managed Threads)

Классификация потоков в .NET

В .NET среда выполнения (CLR) разделяет потоки на два фундаментальных типа:

  1. Неуправляемые потоки (Unmanaged Threads):
    - Выполняют
    нативный код (C++, Rust, системные вызовы)
    - Обрабатывают
    внутренние операции CLR (сборка мусора, JIT-компиляция)
    -
    Ключевая особенность: Не приостанавливаются во время фазы "stop-the-world" GC
    Пример: Потоки, выполняющие код сборщика мусора (GC)
  2. Управляемые потоки (Managed Threads):
    - Выполняют
    управляемый код (C#, F#, VB.NET)
    - Содержат
    расширенный контекст выполнения:
    - Информация о безопасности (SecurityContext)
    - Локальные данные потока (Thread-Local Storage)
    - Контекст синхронизации (SynchronizationContext)
    - Настройки культуры (CultureInfo)
    - Приостанавливаются во время фазы "stop-the-world" GC

Жизненный цикл: Foreground vs Background

Thread workerThread = new Thread(DoWork);
workerThread.IsBackground = true; // Фоновый режим
workerThread.Start();

  • Foreground потоки:
    - Приложение не завершится, пока работает хотя бы один foreground-поток
    - По умолчанию все создаваемые потоки - foreground
  • Background потоки:
    - Автоматически завершаются при закрытии приложения
    -
    Опасность: Могут быть прерваны в любой точке выполнения (включая finally блоки)
    - Устанавливаются явно через IsBackground = true

Работа с Thread API

Создание и управление:

// Создание абстракции потока (нативный поток еще не создан)
Thread myThread = new Thread(WorkerMethod);

// Запуск нативного потока ОС
myThread.Start(argument);

// Ожидание завершения (блокирует текущий поток)
myThread.Join(TimeSpan.FromSeconds(5)); // С таймаутом

Управление выполнением:

Thread.Sleep(15); // Гарантированное переключение контекста (~15 мс)
Thread.Sleep(0); // Переключение на поток с равным/высшим приоритетом
Thread.Yield(); // Добровольная передача процессора (только текущее ядро)
Thread.SpinWait(100); // Активное ожидание без переключения контекста

Отмена выполнения

Устаревший подход (опасен!):

// Прерывание в произвольной точке кода (Obsolete в .NET Core+)
thread.Abort();

// Прерывание только в точках ожидания
thread.Interrupt();

Современный подход через CancellationToken:

using var cts = new CancellationTokenSource();
cts.CancelAfter(3000); // Автоотмена через 3 секунды

var task = Task.Run(() =>
{
cts.Token.ThrowIfCancellationRequested();
// Работа с периодической проверкой токена
}, cts.Token);

// Регистрация колбэка при отмене
cts.Token.Register(() => Console.WriteLine("Отмена!"));

Ключевые особенности управляемых потоков

  1. Соотношение 1:1:
    Каждый managed thread соответствует одному потоку ОС
    Но: Поток ОС может использоваться разными managed threads последовательно
  2. Переключение контекста:
    Дороже, чем в нативных приложениях (+15-20% из-за контекста CLR)
    Включает сохранение: стека вызовов, TLS, безопасности
  3. Статусы потоков:
    Unstarted, Running, WaitSleepJoin, Stopped
    Аналогичны состояниям потоков ОС, но с доп. состояниями CLR