如何检测主线程何时终止?

我需要知道的是:

我想检测主线程(进程?)何时终止,以便我可以确保在终止之前执行某些操作。

我发现自己:

我发现了事件AppDomain.DomainUnloadAppDomain.ProcessExitAppDomain.DomainUnload似乎适用于非应用程序,如MbUnit。 AppDomain.ProcessExit似乎适用于应用程序,但有3秒的时间限制,我真的不喜欢。 是否有更多方法可以检测AppDomain /进程何时终止?

背景:

我正在寻找这样的事件,以确保我的日志在应用程序终止时持久存档。 实际的日志记录使用生产者 – 消费者模式在另一个线程上运行,其中日志条目很可能在内存中排队,我需要确保在应用程序终止时将此队列保存到文件中。

还有什么我应该知道的吗?

更新:

改变了上述内容以反映我自己发现的内容。 我对ProcessExit中的3秒时间限制感到不满意。 MSDN文档确实说它可以扩展:

所有ProcessExit事件处理程序的总执行时间都是有限的,就像所有终结器的总执行时间在进程关闭时受限一样。 默认值为三秒,可以由非托管主机覆盖。

有谁知道如何覆盖默认值?

更多的想法也非常感谢!

跟进:

我已向此发布了一个跟进问题 。

您应该有一个应用程序的入口点。 通常,当所有任务终止时,您可以执行一些日志记录:

 static void Main() { try { Application.Run( .... ); } finally { // logging ... } } 

你究竟想知道什么?

  • 当流程终止时? (仅仅因为AppDomain被卸载并不一定意味着整个过程正在终止)
  • 当主线程终止时(如果有其他非后台线程,主线程可以在没有进程终止的情况下终止(或者AppDomain卸载)

所以他们不是一回事。

无论如何,将日志消息缓存在内存通常是危险的。 如果有人关掉电源怎么办? 或者,如果我通过任务管理器终止您的流程? 您的所有日志消息都消失了。 通常,您需要在日志中进行无缓冲写入,以便立即将消息推送到磁盘。

无论如何,另一种(更强大的)方法可能是在非后台线程中运行记录器本身。 这样,即使应用程序的其余部分终止,记录器也不会,因此进程保持活动状态。 然后你只需要在应用程序的其余部分终止时设置一些标志,让记录器知道它一旦写出所有挂起的日志消息就应该关闭。

它仍然不会让您免于系统断电或有人强行终止操作系统级别的过程,但它会处理应用程序正常关闭的所有情况,并为您提供无限时间执行清理操作(由于该过程实际上还没有终止,它仍然有一个实时线程)

即。 保证被叫,有无限的时间完成?

不幸的是,NO选项将有无限的时间,并得到保证。 没有办法强制执行此操作,因为很多事情都可能发生。 有人绊倒电源线或强行终止你的程序将阻止任何选项给你足够的时间来处理事情。

通常,将逻辑放在Main例程的末尾可能是最合理的选项,因为这样可以让您完全自由地处理终止事件。 您没有时间限制,可以根据需要花费尽可能多的时间。

但是,无法保证这会运行,因为强制终止您的程序可能会完全绕过它。

根据文档,看起来默认的应用程序域(您的Main方法可能正在运行的域)将不会收到DomainUnload事件。

我不知道一个内置事件会做你期望的事情。

您可以定义自己的自定义事件 ,让感兴趣的各方注册,并在从Main()返回之前触发事件。

我不知道这个post多大了,但是我遇到了类似的问题,这对我来说有点难以解决。

我有一个WinForms应用程序,当用户退出时没有触发上述任何事件。 尝试重新运行Application.Run()最终也无法正常工作。

现在要解决这个问题,你必须使用PInvoke进入Win32 API来实现这一目标。 那么你还是在.NET 2.0之前做过。 幸运的是,MS推出了一个名为SystemEvents的新类。 使用此类,您可以捕获SessionEnd事件。 此事件允许您在操作系统要终止您的应用程序时进行清理。 它出现此事件没有.NET时间限制,但如果花费太长时间操作系统最终会终止您的应用程序。 这有点超过3秒,虽然3秒应该有足够的时间进行清理。

其次我的另一个问题是我希望我的工作线程在完成其工作后终止主线程。 使用Application.Run()这很难实现。 我最终做的是使用共享的应用程序上下文调用Application.Run()。 然后该线程可以调用ApplicationContext.ThreadExit()来强制Application.Run返回。 这似乎工作得很好。

希望这有助于某人。

问候

NozFX