受控应用程序关闭策略

时间:2011-06-26 10:43:13

标签: c++ shutdown application-shutdown shutdown-hook

我们的(Windows本机C ++)应用程序由线程对象和管理器组成。编写得非常好,设计中看到Manager对象控制着他们的生命周期。各种对象发送和接收事件;有些活动来自Windows,有些是本土的。

通常,我们必须非常了解线程互操作性,因此我们使用Win32关键部分,信号量等手动同步技术。但是,由于事件处理程序重新入侵等原因,我们偶尔会在关闭期间遇到线程死锁。

现在我想知道是否有一个合适的应用程序关闭策略我们可以实现以便更容易开发 - 比如每个对象从中央控制器注册关闭事件并相应地更改其执行行为?这太天真还是脆弱?

我更喜欢没有规定重写整个应用程序以使用Microsoft的Parallel Patterns Library或类似的策略。 ; - )

感谢。

编辑:

我想我要求在复杂的应用程序中控制对象生命周期的方法,其中许多线程和事件一直在触发。 Giovanni的建议很明显(我们自己动手),但我确信必须有各种现成的策略或框架,以正确的顺序干净地关闭活动对象。例如,如果您希望将C ++应用程序基于IoC范例,则可以使用PocoCapsule而不是尝试开发自己的容器。在应用程序中控制对象生命周期有类似的东西吗?

3 个答案:

答案 0 :(得分:3)

这似乎是更普遍的问题的一个特例,“如何在多线程应用程序中避免死锁?”

答案就是一如既往:确保你的线程一次获得多个锁,他们都以相同的顺序获取锁,并确保所有线程都释放锁在有限的时间内。此规则适用于关机时的任何时间。没有什么比这更好了;没有必要。 (参见here进行相关讨论)

至于如何最好地做到这一点......最好的方法(如果可能的话)是尽可能地简化你的程序,并且如果你可以帮助它,一次避免持有多个锁。

如果您绝对必须一次拥有多个锁,则必须验证您的程序以确保每个拥有多个锁的线程以相同的顺序锁定它们。像helgrind or Intel thread checker这样的程序可以帮助解决这个问题,但它往往归结为简单地关注代码,直到你向自己证明它满足这个约束。此外,如果您能够轻松地重现死锁,您可以检查(使用调试器)每个死锁线程的堆栈跟踪,这将显示死锁线程永远被阻塞的位置,并且通过该信息,您可以开始找出代码中锁定顺序不一致的位置。是的,这是一个很大的痛苦,但我不认为有任何好的方法(除了避免同时持有多个锁)。 :(

答案 1 :(得分:1)

作为一般方法,使用原子布尔值来表示“我正在关闭”,然后每个线程在获取每个锁之前检查此布尔值,处理每个事件等。除非您给我们一个,否则不能给出更详细的答案更详细的问题。

答案 2 :(得分:1)

一种可能的一般策略是向每位经理发送“我正在关闭”事件,这会导致经理做三件事之一(取决于你的事件处理程序的运行时间,以及延迟时间)你想要在用户启动关闭和实际退出的应用程序之间。

  

1)停止接受新事件,并为“我正在关闭”事件之前收到的所有事件运行处理程序。为避免死锁,您可能需要接受对完成其他事件处理程序至关重要的事件。这些可以通过事件中的标志或事件的类型(例如)来发出信号。如果您有此类事件,那么您还应该考虑重构代码,以便不通过事件处理程序执行这些操作(因为依赖事件在普通操作中也容易出现死锁。)

     

2)停止接受新事件,并丢弃在处理程序当前正在运行的事件之后收到的所有事件。关于依赖事件的类似评论也适用于这种情况。

     

3)中断当前正在运行的事件(具有类似于boost::thread::interrupt()的功能),并且不再运行任何事件。这要求您的处理程序代码是异常安全的(如果您关心资源泄漏,它应该已经存在),并且要以相当规律的间隔输入中断点,但这会导致最小的延迟。

当然,您可以将这三种策略混合在一起,具体取决于每位经理的特定延迟和数据损坏要求。