【问题标题】:IDisposable code on process termination进程终止时的 IDisposable 代码
【发布时间】:2011-12-04 13:44:37
【问题描述】:

我有一个很好的老式 Windows 服务(继承自 System.ServiceProcess.ServiceBase),我通过this.components.Add(new MyStuff());向其中添加了一个组件(实现 IComponent)
但是,如果我从任务管理器关闭 exe,MyStuff 的 Disposable() 不会运行。

可能的嫌疑人:

  • “结束进程”上没有运行。如果是这样,我该如何清理自己(例如杀死已启动的进程?)
  • 出于测试目的,我使用

    开始我的服务

    var service = new MyService();
    service.Run();
    Thread.Wait(Timeout.Infinite);

    这不是ServiceBase.Run(new []{new MyService()}); 的问题吗?

  • ServiceBase 不会自动清理。如果是这样,我该怎么办?

请帮忙!

附加信息:我正在尝试使用 Process.Start(...) 关闭我从我的服务启动的其他 exe,所以如果有办法让它们自动关闭(子进程?)也很好。

【问题讨论】:

  • 这看起来可能是相关的:stackoverflow.com/questions/3342941/…
  • 如果您可以同时更改父进程和子进程中的代码,那么在子进程中拥有检测父进程死亡并自动杀死子进程的代码可能会更容易。
  • @Damien_The_Unbeliever:我如何检测到它?我是否检查是否有任何与我的父母同名的进程?没有更好的吗?
  • 除其他问题外,还请注意,不能保证终结器将在进程终止时运行。如果你的终结器花费的时间太长,CLR 就会放弃。

标签: c# .net process windows-services idisposable


【解决方案1】:

如果你“拔掉插头”,那一刻你什么也做不了。它不被视为受控关闭。这是完全出乎意料的,没有什么能让你有能力从被杀死的进程内部处理它。它甚至不被视为关闭。明确一点:您不是在关闭,而是在杀死它!就像从计算机上拔下电源线并期望它正常关机一样。不会工作(尽管几年前我有一个测试人员为我写了这个非常精确的测试用例......)

解决它:

  • 您的子进程需要“ping”父进程。如果它没有响应,您就知道有问题并正常关闭。

  • 或者参考ChrisBint(Service Controller)的回答。按名称获取服务,启动和停止它。

在此处查找示例代码: http://www.csharp-examples.net/restart-windows-service/

【讨论】:

  • 如果父进程死于未处理的异常,它会响应吗?另外,如何ping父进程?我没有找到 Process.GetCurrent().Parent 或类似的东西
  • 从任务管理器中终止与死于未处理的异常不同。从任务管理器中终止是从轨道启动,而未处理的异常是从进程内部生成的(因此您有机会捕获它)。
  • 如果它死了,它不会回复(或者它不会那么死,对吧?)。你通过任务管理器杀了它,它不会再响应了。它消失了。有关一些示例,请参阅我编辑的答案。
  • @RaymondChen 你说得对,我指的是“通过任务管理器杀死”场景
【解决方案2】:

我让孩子发现父母死亡的典型方式:

  • 在父启动期间,生成一个漂亮、长、随机的名称
  • 同样在启动期间,获取具有此名称的命名互斥体,并在父项的生命周期内保持锁定状态。
  • 启动子进程时,将长随机名称作为参数传递
  • 在子级中,专用一个线程来尝试获取同名互斥锁。
  • 如果子进程获得了互斥锁,父进程肯定已经死亡 - 所以子进程也应该退出

通过为互斥体使用随机名称,您可以确保即使旧的父/子层次结构正在关闭,也可以构建新的层次结构。

【讨论】:

  • 这听起来不错。如果父级死于未处理的异常,互斥锁会被释放吗?
  • 是的。来自.Net Mutex class:“对于系统范围的互斥锁,废弃的互斥锁可能表明应用程序已被突然终止(例如,通过使用 Windows 任务管理器)。”
  • 更简单的是Process.GetProcessById(parentId).WaitForExit()
【解决方案3】:

你为什么要使用任务管理器停止服务,你基本上是在杀死它,而不是要求它做某事。

在 OnStop 方法中放一些代码来清理和使用服务管理器来停止/启动服务。

【讨论】:

  • 我正在使用任务管理器停止它,因为我正在模拟“突然崩溃”
  • 我想也许 TDaver 也想处理从任务管理器关闭服务的情况?一种“以防万一”的措施。
  • 什么是你想清理的,不会仅仅通过进程终止来清理的?
  • 如上所述,我已经启动了另一个不会退出的exe(进程)!
猜你喜欢
  • 1970-01-01
  • 2014-10-27
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
  • 1970-01-01
相关资源
最近更新 更多