记一个dotnet core控制台优雅退出的问题

安全退出,收到退出指令后, 让所有线程安全执行完在退出。测试环境Ubuntu. Daemon和普通的console都测试, 看Ubuntu在退出是是否等待Console执行完。

起作用的是另一个事件

System.Runtime.Loader.AssemblyLoadContext.Default.Unloading

 

 

 

Main方法中,我把三类事件捕捉,看哪个起作用

这是我们的等待退出逻辑,在wile循环结束后,又等待5秒,是为了让日志输出完,根据需要调整

 

 

 

这是模拟一个起动线程的类,线程类的方法如下:

 

 

 

可以看到,当CancellationTokenSource被请求退出时,会break while(true)循环,上面我们有个等待退出的方法中,有个等待5秒,其实就是为了这里的Log.输出日志。这个只是为了展示,我们的确是待一个循环完成后才安全退出的,如果实际操作中不需要输出日志,也就不用等待5秒了。

 

再详细请参看一下代码

 

下面看一下各环境运行情况

windows vs 调试状态

 

 

 

运行起来,点右上角的X号关闭

 

 

 

结果如下:

 

 

 

下面看一下docker中。

Dockfile如下:

注,我上面有apt-get install procps,是为了演示用的,为了在container安装ps命令,方便查看各个进程的pid.

 

 

 

 

 

 

 

 

 

进入container,试一下console方式的运行和结束

 

 

 

再开一个终端,查看container内的进程

PID1就是 run container 的主进程,另一个PID34就是我们console启动的进程,我们先试一下kill console进程的结果

 

 

 生成了日志,我们把日志拿出来看一下,因为我没有装vi/vim,我给copy到宿主机看

 

 

 

 

 

OK,下面再试一下kill Container怎么样。

先进container删掉日志,看kill container会不会生成。

 

 

 

 

 

 可见用这样直接Kill 方式不行。再试另一种方式

 

 

 这次有日志了

 

 

 

 

 

 是我们要的结果。

再看一下docker kill 的help 发现上面我们kill 没有发信号,所以失败了。再试一次

 

 

 

 

 看到有日志了,我再拷出来看一下对不对

 

 

 可以看到没问题 了。

 

以上就是所有的测试过程和结果。记录一下,备忘。

 

真正起作用的,是

1  System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += (ctx) =>
2             {
3                 Log.Information("Closing");
4                 System.Console.WriteLine("Closing");
5                 WaitThreadExit();
6             };

 

结束,谢谢观赏。

 追加:

https://docs.microsoft.com/en-us/windows/console/handlerroutine?redirectedfrom=MSDN

https://docs.microsoft.com/zh-cn/dotnet/api/system.appdomain.processexit?view=netcore-3.1

 

 在windows 控制台,直接点右上角的X,还是不行,因为默认的退出时间最多为5秒

 

posted @ 2020-10-27 13:12  浪客是剑心  阅读(2518)  评论(0编辑  收藏  举报