Что такое зависание программы?

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

Ответ

Зависание (или "заморозка") программы — это состояние, когда приложение перестает реагировать на пользовательский ввод или внешние события. Основные причины:

1. Бесконечные или длительные циклы

// Явный бесконечный цикл
while (true) { }
// Длительная синхронная операция
for (int i = 0; i < 1000000000; i++) { ProcessData(i); }

2. Взаимная блокировка (Deadlock) Возникает, когда два или более потока блокируют ресурсы, ожидая друг друга.

// Поток 1
lock (resourceA) {
    // Ждет resourceB
    lock (resourceB) { ... }
}
// Поток 2 (делает наоборот)
lock (resourceB) {
    lock (resourceA) { ... } // Взаимная блокировка
}

3. Блокировка UI-потока Выполнение тяжелых синхронных операций в потоке интерфейса.

// ПЛОХО: Блокирует UI на 5 секунд
void Button_Click() {
    Thread.Sleep(5000); // Приложение "висит"
}

// ХОРОШО: Асинхронный подход
async void Button_Click() {
    await Task.Delay(5000); // UI остается отзывчивым
}

4. Ожидание завершения задачи, которая никогда не завершится Например, Task.Wait() или Task.Result на задаче, зависшей из-за deadlock.

Стратегии предотвращения:

  • Для I/O операций: Используйте async/await паттерн.
  • Для CPU-интенсивных задач: Выносите в фоновые потоки через Task.Run.
  • Для отмены: Применяйте CancellationTokenSource и CancellationToken.
  • Для анализа: Используйте инструменты вроде Concurrency Visualizer, PerfView или дампы памяти для диагностики.
  • В UI: В WPF/WinForms соблюдайте правило — UI-поток только для обновления интерфейса.