Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何检测主线程何时终止?_C#_.net_Multithreading_Logging - Fatal编程技术网

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

C# 如何检测主线程何时终止?,c#,.net,multithreading,logging,C#,.net,Multithreading,Logging,我需要知道的是: 我想检测主线程(进程?)何时终止,以便确保在终止前执行某些操作 我所发现的: 我找到了事件AppDomain.DomainUnload和AppDomain.ProcessExitAppDomain.DomainUnload似乎适用于MbUnit等非应用程序AppDomain.ProcessExit似乎适用于应用程序,但有一个3秒的时间限制,我真的不喜欢。是否有更多方法可以检测AppDomain/进程何时终止 背景: 我正在寻找这样一个事件,以确保在应用程序终止时我的日志持久化到

我需要知道的是:

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

我所发现的:

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

背景:

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

还有什么我应该知道的吗

更新:

改变以上内容以反映我自己的发现。我对ProcessExit期间的3秒时间限制不满意。MSDN文档确实指出,它可以扩展:

所有操作的总执行时间 ProcessExit事件处理程序有限, 正如 所有终结器在进程中都受到限制 关闭。默认值为3 秒,可由 非托管主机

有人知道如何覆盖默认值吗

更多的想法也被高度赞赏

跟进:


.

根据文档,默认应用程序域(您的主要方法可能正在运行的域)似乎不会接收DomainUnload事件

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


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

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

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

你到底想知道什么

  • 进程何时终止?(卸载AppDomain并不一定意味着整个进程正在终止)
  • 当主线程终止时(如果存在其他非后台线程,则主线程可以在进程不终止(或AppDomain卸载)的情况下终止)
所以它们不是完全一样的东西

无论如何,在内存中缓冲日志消息通常是很危险的。如果有人关闭电源,或者如果我通过任务管理器终止您的进程,会发生什么情况?您的所有日志消息都会消失。通常,您希望在日志中进行无缓冲写入,以便将消息立即推送到磁盘

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

在系统断电或有人在操作系统级别强制终止进程的情况下,它仍然不会为您节省时间,但它将处理应用程序正常关闭的所有情况,并为您提供无限时间执行清理操作(因为进程实际上还没有终止,它仍然有一个活动线程)

也就是说,保证会打电话,并且有无限的时间来完成

不幸的是,没有一个选项会有无限的时间,而且是有保证的。没有办法强制执行这一点,因为很多事情都可能发生。有人被电源线绊倒或强制终止您的程序将阻止任何选项给您足够的时间来处理事情

一般来说,将逻辑放在主例程的末尾可能是最合理的选择,因为这样可以让您完全自由地处理终止事件。您没有时间限制,并且可以让处理花费所需的时间


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

我不知道该线程有多老,但我遇到了一个类似的问题,这对我来说有点难解决

我有一个WinForms应用程序,当用户注销时,该应用程序没有触发上述任何事件。在尝试中包装应用程序。Run()最终也不起作用

现在要解决这个问题,你必须在Win32 API中使用PInvoke来实现这一点。不管怎样,你在.NET 2.0之前就做过。幸运的是,MS引入了一个名为SystemEvents的新类。通过这个类,你可以捕获SessionEnd事件。这个事件允许你在操作系统想要终止你的应用程序时进行清理。这个事件没有.NET时间限制看起来是这样的,不过如果你花的时间太长,操作系统最终会杀死你的应用。这比3秒多一点,虽然3秒应该是清理的足够时间

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

希望这对别人有帮助

问候


NozFX

听起来有点像黑客:-)。我希望有更好的解决办法。谢谢你的主意!顺便说一句,关于域,你是对的。卸载在应用程序中不工作。该死。听起来好像DomainUnload是为了在其他应用程序需要时提供一个事件