Какая разница между Environment.Exit() и Application.Shutdown()?

Иногда приложение не может выйти, когда я вызывал Application.Shutdown, пользовательский интерфейс был закрыт, но процесс все еще работает. как закрыть приложение с закрытием всех потоков? может ли Environment.Exit() закрыть все потоки? или мы должны вызвать Win32 API TerminateThread, чтобы сделать это?

Ответ 1

Environment.Exit() - более жестокий способ закрыть приложение, но в целом, если вам нужно убить приложение чтобы закрыть его, я думаю, что вы рассматриваете проблему не так. Вы должны лучше изучить, почему не закрываются другие потоки?

Вы можете заглянуть в событие FormClosing в основной форме и закрыть все ресурсы, которые подвешивают приложение, не позволяя ему закрыться.

Вот как я нашел ресурсы, зависящие от приложения.

  • В режиме отладки включите показ threads (это позволит вам видеть все потоки, на которые запущено приложение)
  • Закройте приложение так, чтобы оно не было правильно закрыто.
  • Нажмите кнопку паузы в Visual Studio
  • Посмотрите на список тем и щелкните по ним, чтобы увидеть, где он находится в коде, который они висят, теперь, когда вы можете видеть, какие ресурсы блокируют ваше приложение от закрытия, перейдите к событию FormClosing и закройте его /Dispose.
  • Повторяйте до тех пор, пока приложение не закроется правильно:)

Имейте в виду, что список потоков в режиме отладки покажет некоторые потоки, которые запускаются, но не под вашим контролем, эти потоки имеют имя, и когда вы нажимаете на них, вы получаете сообщение о том, что у вас нет символов. Их можно безопасно игнорировать.

Одна из причин того, что ваше приложение закрывается грациозно, заключается в том, что если некоторые ресурсы (скажем, FileStream) не сделав работу, поэтому, используя некоторые api, чтобы заставить ее быстро, могут возникнуть всевозможные "случайные" проблемы, например, файлы настроек/данных, которые не записываются, и т.д.

Ответ 2

  • Вы должны НИКОГДА позвонить TerminateThread
  • Убедитесь, что все потоки, которые вы создавали, отмечены как фон, таким образом, когда вы закрываете приложение, оно не будет ждать их завершения.

Ответ 3

Как сказал Шей, НИКОГДА не называйте TerminateThread, TerminateThread убивает только один поток, не позволяя ему очищаться после себя, это может привести к взаимоблокировкам и искажениям в других потоках процесса.

TerminateProcess с другой стороны убьет весь процесс и позволит ОС очистить, это самый быстрый способ закрыть процесс - вам просто нужно убедиться, что вы не держите никаких ресурсов, которые ОС не может очистить (это также помогает закрыть окна перед вызовом TerminateProcess).

Я думаю, но я не проверял, что Environemnt.Exit вызывает TerminateProcess.

Application.Shutdown очень отличается, он не сразу убивает процесс - он отправляет все уведомления о закрытии и завершении работы и ждет, чтобы все окна приложений и потоки закрылись.