安全退出,收到退出指令后, 让所有线程安全执行完在退出。测试环境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秒