受控应用程序关闭策略

Controlled application shut-down strategy

本文关键字:策略 应用程序      更新时间:2023-10-16

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

一般来说,我们必须非常清楚线程的互操作性,因此我们使用Win32关键部分、信号量等手动同步技术。然而,偶尔我们会在关闭期间遇到线程死锁,这是由于事件处理程序重新进入之类的原因。

现在,我想知道我们是否可以实施一种像样的应用程序关闭策略,使其更容易开发——比如每个对象都从中央控制器注册关闭事件,并相应地改变其执行行为?这是太天真还是太脆弱了?

我更喜欢那些没有规定重写整个应用程序的策略,以使用微软的并行模式库或类似程序

谢谢。

编辑:

我想我是在寻求一种方法来控制复杂应用程序中的对象生命周期,在这个应用程序中,许多线程和事件一直在启动。Giovanni的建议是显而易见的(我们自己动手),但我相信必须有各种现成的策略或框架,才能以正确的顺序干净地关闭活动对象。例如,如果你想将C++应用程序建立在IoC范式的基础上,你可以使用PocoCapsule,而不是尝试开发自己的容器。在应用程序中控制对象生命周期有类似的方法吗?

这似乎是"如何避免多线程应用程序中的死锁?"

答案是,一如既往:确保任何时候你的线程都必须一次获取多个锁,它们都以相同的顺序获取锁,并确保所有线程在有限的时间内释放锁。这个规则在关机时和其他任何时候一样适用。再少也不够好;没有什么必要了。(相关讨论请参见此处)

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

如果您绝对必须一次持有多个锁,则必须验证您的程序,以确保持有多个锁定的每个线程都以相同的顺序锁定它们。像helgrind或Intel线程检查器这样的程序可以帮助实现这一点,但它通常可以归结为简单地观察代码,直到你向自己证明它满足这一限制。此外,如果您能够轻松地再现死锁,您可以检查(使用调试器)每个死锁线程的堆栈跟踪,这将显示死锁线程永远被阻塞的位置,有了这些信息,您就可以开始了解代码中锁顺序不一致的位置。是的,这是一个很大的痛苦,但我认为没有任何好的方法来解决它(除了避免同时持有多把锁)。:(

一种可能的通用策略是向每个管理器发送一个"我正在关闭"事件,这将导致管理器执行三件事中的一件(取决于事件处理程序运行的时间,以及用户启动关闭和应用程序实际退出之间的延迟)。

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

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

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

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

作为一种通用方法,使用一个原子布尔值来表示"我正在关闭",然后每个线程在获取每个锁、处理每个事件等之前都会检查这个布尔值。除非你给我们一个更详细的问题,否则无法给出更详细的答案。