В отличие от C ++, потоки в .NET по умолчанию поддерживают работу приложения, даже если основной поток выполняется до конца метода main()
. Это означает, что все остальные потоки в вашем приложении также должны достичь своего конца.
Конечно, есть исключения из этого правила:
- " background " будет прерван
- вам не нужно заботиться о потоках сборщика мусора и финализатора
- .NET позаботится о потоках пула потоков
- (потенциально другие)
Если вы скажете: «Я все это знал и обдумывал», это нормально. Есть множество XXXX
потоков, что указывает на то, что эти темы умерли. И это хорошо, если вы хотите, чтобы приложение закрылось.
Так что в остальных темах может возникнуть тупик. Может произойти взаимоблокировка с любым объектом синхронизации, а не только с оператором lock
. В .NET у нас их много:
lock
выписка
Monitor
(по сути то же самое)
ReaderWriterLock
ReaderWriterLockSlim
Process
Thread
SpinLock
CountDownEvent
- ...
И, что еще хуже, используя P / Invoke, мы также можем получить доступ ко всем собственным объектам синхронизации:
Mutex
Semaphore
Event
WaitableTimer
CriticalSection
Job
- ...
Проблема в том, что все эти объекты синхронизации делают отладку тупиком довольно сложной. Положительная сторона: у вас есть все время, которое вы хотите, потому что приложение ждет, когда вы его проанализируете.
Мои предложения по анализу тупиковой ситуации:
- Взять аварийный дамп . Многие разработчики не знают, что аварийный дамп все еще полезен, даже если приложение не аварийно завершило . Это полезно в случае самопроизвольных перезагрузок компьютера, например, установки обновлений Windows.
- В случае .NET запустите sosex
!dlk
. Это специализированная команда для взаимоблокировок, которая рассматривает операторы lock
, Monitor
, ReaderWriterLock
и native CriticalSection
. Это экономит время.
!analyze -hang
неплохо дает вам отправную точку вашего анализа. Это часто не определяет всю цепочку ожидания, но хорошая отправная точка имеет решающее значение.
Если вы беспокоитесь о «убегающих» потоках, тогда живое приложение намного лучше. Активный поток должен потреблять процессор, который вы можете видеть в таких инструментах, как Process Explorer . Сделайте следующее:
- Сконфигурируйте символы, если вы хотите сразу увидеть хорошие стеки вызовов
- Открыть свойства затронутого процесса
- Перейти на вкладку «Темы»
- Остерегайтесь ниток, в которых много "Cycles Delta". Инструмент выдаст вам идентификатор этого потока.
В этом случае вам необходимо выяснить, как отменить операцию, над которой работает поток, или отобразить индикатор выполнения, чтобы пользователь мог определить, когда программа завершит работу.
Предполагая, что вы ожидали завершения программы более 16 секунд, неудовлетворительный поток, скорее всего, не ваша проблема.