В чем разница между Environment.Exit() и Application.Shutdown()?
Иногда приложение не может выйти, когда я вызвал Application.Shutdown, пользовательский интерфейс был закрыт, но процесс все еще выполняется. как закрыть приложение с закрытием всех потоков? Environment.Exit() может закрыть весь поток? или мы должны вызвать Win32 API TerminateThread, чтобы сделать это?
3 ответа
Environment.Exit() - это более жестокий способ закрытия вашего приложения, да, но в целом, если вам нужно убить ваше приложение, чтобы закрыть его, то я думаю, что вы смотрите на проблему неправильно. Вам лучше разобраться, почему другие темы не закрываются изящно?
Вы можете просмотреть событие FormClosing в главной форме и закрыть все ресурсы, которые вешают приложение, предотвращая его закрытие.
Вот как я нашел ресурсы, вешающие приложение.
- В режиме отладки включите отображение потоков (это позволит вам увидеть все потоки, которые запускает ваше приложение)
- Закройте приложение так, чтобы оно не закрывалось правильно.
- Нажмите паузу в Visual Studio
- Посмотрите на список потоков и нажмите на них, чтобы увидеть, где в коде они висят, теперь, когда вы можете увидеть, какие ресурсы блокируют закрытие вашего приложения, перейдите к событию FormClosing и закройте / утилизируйте их там.
- Повторяйте, пока приложение не закроется правильно:)
Имейте в виду, что в списке потоков в режиме отладки будут показаны некоторые потоки, которые запущены, но не находятся под вашим контролем, эти потоки обычно имеют имя, и когда вы нажимаете на них, вы получаете сообщение о том, что у вас нет символов. Их можно игнорировать
Одна из причин того, что ваше приложение корректно закрывается, заключается в том, что если некоторые ресурсы (скажем, FileStream) не работают, поэтому использование некоторых API для ускорения может привести к возникновению всевозможных "случайных" проблем, таких как файлы настроек / данных не пишутся и так далее.
- Вы никогда не должны вызывать TerminateThread
- Убедитесь, что все потоки, которые вы создали, помечены как фоновые, поэтому при закрытии приложения он не будет ждать их завершения.
Как сказал Шей, НИКОГДА не вызывайте TerminateThread, TerminateThread убивает только один поток, не давая ему очиститься после себя, это может привести к взаимным блокировкам и повреждениям в других потоках в процессе.
TerminateProcess, с другой стороны, уничтожит весь процесс и позволит очистить ОС, это самый быстрый способ закрыть процесс - нужно просто убедиться, что у вас нет ресурсов, которые ОС не может очистить (это также помогает закрыть окна перед вызовом TerminateProcess).
Я думаю, но я не проверял, что Environemnt.Exit вызывает TerminateProcess.
Application.Shutdown сильно отличается, он не сразу убивает процесс - он отправляет все уведомления о закрытии и завершении работы и ожидает закрытия всех окон и потоков приложения.