[英]Proper thread termination in multi-threaded C# application
我认为这是一个相当复杂的问题。 我有一个C#应用程序,它使用反射的插件架构。 应用程序加载插件dll,用户可以启用/禁用它们。 启用插件后,主应用程序会启动一个线程来运行插件。在许多情况下,插件可能有多个自己的线程。 当我想禁用一个插件时,我正在调用Thread.Abort()。 这似乎会破坏为插件创建的初始线程,但插件创建的任何其他线程都会继续运行。 有没有更好的方法来阻止所有相关的插件线程和主线程?
谢谢。
不要将Thread.Abort
用于此目的。
添加Shutdown
方法或类似于您的插件API,并要求您的插件干净地关闭。 如果您需要保护自己免受拒绝关闭的恶意插件的影响,请在他们自己的AppDomain中运行它们并在必要时终止AppDomain。
我会在插件中设置一个我希望关闭它的标志,插件本身应该定期检查标志是否已设置,如果是,它应该自行清理。 这种方法最适合使用一段while(true) {...}
种线程体。
如果您使用基于事件的aproach与大量的WaitForSingleObject
,我会使用一个事件,当我想要插件关闭时,我将脉冲,我将事件添加到WaitForMultipleObjects
列表进行检查。
这实际上取决于您的插件如何运行以及它的编码方式。 尝试提供更多信息。
Thread.Abort
是一种可怕的方式,它根本不进行任何清理。
是的,不要使用Abort。 当我想终止执行时,我会使用ManualResetEvent来发出信号,例如使用循环:
ManualResetEvent _stopping = new ManualResetEvent(false);
...
while (!_stopping.WaitOne(0))
{
...
}
当你想要停止循环时发出信号:
public void Stop()
{
_stopping.Set();
}
然后使用Thread.Join,如果你想等到线程终止。 如果没有及时,你可以打电话给Abort。
在您的情况下,您应该真正将加载项加载到单独的AppDomain中,并在完成后卸载它。 您可能希望构建一个模型,在该模型中,当它们即将关闭时,您也会发送加载项通知。
我知道没有办法询问线程有关谁可能声称自己是拥有者的线索。 这基本上意味着你需要在你的插件API中添加approriate机制来关闭插件实例。 也许您可以在插件界面中添加Shutdown
或Terminate
方法,并使其成为记录合同的一部分,这些合同必须能够很好地清理他们分配的所有资源。
我能想到的唯一另一个策略(这个很糟糕的时候)是跟踪应用程序自己创建的所有线程,然后假设所有其他线程都由插件拥有。 您将不得不中止所有这些线程,因为您无法将它们链接到插件的特定实例。 就个人而言,这听起来像是灾难的秘诀。 我只会探索这个作为最后的手段。
听起来像你在各种程序集上调用任意方法,这些方法可能不是设计为在线程上运行而期望它们可能被取消。
在它自己的线程上运行的插件方法至少应该处理异常并清理它自己的线程。 在线程上调用Thread.Abort()时,会在该线程上抛出ThreadAbortException以终止它。
Thread.Abort()不是在正常条件下终止线程的推荐方法。 更好的方法是在方法中设计一种合作方式,允许您取消它。 如果这是不可能的,只要执行方法偶尔在安全点进入WaitSleepJoin状态(等待WaitHandle,休眠等),调用Thread.Interrupt()是一种更温和的终止线程的方法。 在这种情况下,线程上抛出ThreadInterruptedException。 其他线程仍应在异常处理程序中清理。
其他人都是对的 - 在优雅的关机信号中编码。 但是,如果您无法轻易更改子线程的代码,并且您的计划压力很大,并且如果子线程重置或挂起中止的可能性很小,并且您承诺稍后重构,那么您可以为插件添加一个故障保护,将子线程添加到集合中,然后捕获ThreadAbortException并使集合中止子线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.