.NET应用程序如何在被终止/杀死时优雅地关闭管理

7
我们有一个.NET控制台应用程序,其中有许多前台线程。 如果我们使用任务管理器或在Windows命令行中发出killjob、kill来终止进程,是否有一种方法可以优雅地关闭应用程序(在.NET控制台应用程序中添加托管代码),例如添加一个名为TodoBeforeShutdown()的函数以处理对象的销毁、关闭任何打开的连接等。 附言:我看了其他帖子,它们都提出了不同的终止进程方式,而不是我的具体问题,即在.NET托管代码中如何处理终止进程,希望能得到解答。 提前致谢。
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
11
很不幸,当进程被终止时,没有任何事件被触发,你可以处理它。
你可以将杀死进程看作是切断电源——无论你设计的代码如何,在系统关机时运行,如果计算机没有正常或适当地关闭,那么这段代码就不会运行。 当你使用任务管理器杀死一个进程时,它调用Win32 TerminateProcess函数,这个函数无条件地强制进程(包括所有拥有的线程)退出。 所有线程/进程的执行都停止了,并且所有未决的 I/O 请求都被取消。你的程序实际上已经死亡。 TerminateProcess 函数不会调用CLR提供的关闭序列,因此你的托管应用程序甚至不知道自己正在被关闭。 你认为当你的应用程序进程被终止时需要处理对象的释放,但这里有几件值得指出的事情:
  • 始终努力最小化可能造成的损害。尽早丢弃您使用完毕的对象。不要等到以后再处理。在任何时候,当程序进程终止时,您只应保留最少量的对象,这将减少泄漏的可能性。

  • 操作系统通常会在终止时清理和释放大部分这些资源(例如句柄等)。

  • 最后,应该毫无疑问地说,以这种方式终止进程真正是一种特殊情况——即使有一些资源泄漏,也是可以预料的。您不应该像结束必要的Windows系统进程一样关闭应用程序(即使作为管理员运行时也不应该这样做)。

如果这是您关闭控制台应用程序的常规计划,您需要找到另一个计划


谢谢您的回复。我应该指出,这并不是计划的一部分,而是我们公司批处理调度基础设施中存在的一个限制,它源于Linux终止进程的“礼貌”方式。后来,这种方式被移植到Windows上,并使用kill命令。 - keepsmilinyaar
жңүи¶Јзҡ„жҳҜпјҢвҖңзӨјиІҢжқҖжӯ»вҖқеңЁUnixдё–з•ҢдёӯзӣёеҪ“дёҚеҜ»еёёгҖӮеӨ§еӨҡж•°еҹәдәҺUnixзҡ„ж“ҚдҪңзі»з»ҹе°ҶеҸ‘йҖҒSIGKILLпјҲж— жқЎд»¶пјүиҖҢдёҚжҳҜSIGTERMпјҲзӨјиІҢж–№ејҸпјүд»Ҙе“Қеә”killallе‘Ҫд»ӨжқҘз»ҲжӯўиҝӣзЁӢгҖӮ - Cody Gray
所以你的托管应用程序甚至不会意识到它正在被关闭,这很好,它清楚地表示该应用程序根本不知道它正在被终止。如果你想要记录关闭过程,也无法做到。 - Jim Aho

2
简而言之:你不能这样做!
结束一个进程正好是优雅退出的相反方式。
如果你正在运行前台线程,发送wm_exit将无法关闭你的应用程序。由于你有一个控制台应用程序,你可以简单地重定向控制台输入以向你的进程发送“exit”。
此外,我认为你可以将应用程序更改为服务(而不是控制台应用程序),这将为你提供你所寻找的精确功能 -> 基于Windows内置工具/命令的优雅退出界面。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,