Ответ
Зависание (или "заморозка") программы — это состояние, когда приложение перестает реагировать на пользовательский ввод или внешние события. Основные причины:
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-поток только для обновления интерфейса.