У нас есть настольное приложение WinForms, которое сильно многопоточно. 3 потока выполняются с Application.Run и множеством других фоновых рабочих потоков. Было сложно правильно закрыть все потоки, но я подумал, что наконец все понял.
Но когда мы фактически развернули приложение, пользователи начали ощущать, что приложение не закрывается. Существует System.Threading.Mutex, чтобы они не запускали приложение несколько раз, поэтому им нужно войти в диспетчер задач и убить старый, прежде чем они смогут запустить его снова.
Каждый поток получает Thread.Join до выхода из основного потока, и я добавил ведение журнала к каждому создаваемому потоку. Согласно журналу, каждый отдельный поток, который запускается, также завершается, и основной поток также завершается. Еще более странно то, что запуск SysInternals ProcessExplorer показывает, что все потоки исчезают при выходе из приложения. Как и в случае, есть 0 потоков (управляемых или неуправляемых), но процесс все еще выполняется.
Я не могу воспроизвести это ни на каких компьютерах разработчиков или в нашей тестовой среде, и пока я видел это только в Windows XP (не Vista, Windows 7 или любой другой Windows Server). Как процесс может продолжать работать с 0 потоками?
Редактировать:
Вот еще немного подробностей. В одном из циклов событий размещается библиотека взаимодействия Win32, которая использует COM-объект для взаимодействия с драйвером устройства. Я помещаю его в отдельный поток, потому что драйвер устройства чувствителен ко времени, и всякий раз, когда поток пользовательского интерфейса блокируется на значительное время (например, ожидает завершения вызова базы данных), он мешает работе драйвера устройства.
Поэтому я изменил код, чтобы основной поток выполнял Thread.Join с потоком драйвера устройства. Это фактически привело к тому, что приложение заблокировалось ... оно регистрирует еще несколько вызовов в потоке пользовательского интерфейса после завершения соединения, а затем все останавливается. Если устройство выключено, драйвер не запускается, и проблема исчезает. Таким образом, похоже, что драйвер должен нести ответственность за поддержание работы приложения даже после того, как оно предположительно было закрыто.