在多线程C#应用程序中正确终止线程

时间:2010-04-23 19:23:54

标签: c# multithreading

我认为这是一个相当复杂的问题。我有一个C#应用程序,它使用反射的插件架构。应用程序加载插件dll,用户可以启用/禁用它们。启用插件后,主应用程序会启动一个线程来运行插件。在许多情况下,插件可能有多个自己的线程。当我想禁用一个插件时,我正在调用Thread.Abort()。这似乎会破坏为插件创建的初始线程,但插件创建的任何其他线程都会继续运行。有没有更好的方法来阻止所有相关插件的线程和主线程?

感谢。

7 个答案:

答案 0 :(得分:7)

请勿将Thread.Abort用于此目的。

为您的插件API添加Shutdown方法或类似方法,并让您的插件干净地关闭。如果您需要保护自己免受拒绝关闭的恶意插件的影响,请在他们自己的AppDomain中运行它们,并在必要时杀死AppDomain。

答案 1 :(得分:1)

我会在插件中设置一个我希望关闭它的标志,并且插件本身应该定期检查标志是否已设置,如果是,它应该自行清理。这种方法最适合while(true) {...}种线程体。

如果您使用的是基于事件的aproach,并且有很多WaitForSingleObject,我会使用一个事件,当我希望插件关闭时我会发出脉冲,并且我会添加事件到要检查的WaitForMultipleObjects列表。

这实际上取决于您的插件如何运行以及它的编码方式。尝试提供更多信息。

Thread.Abort是一种可怕的方式,它根本不会进行任何清理。

答案 2 :(得分:1)

是的,不要使用Abort。当我想终止执行时,我会使用ManualResetEvent来发出信号,例如:循环:

ManualResetEvent _stopping = new ManualResetEvent(false);
...
while (!_stopping.WaitOne(0))
{
    ...
}

当你想要停止循环时发出信号:

public void Stop()
{
    _stopping.Set();
}

然后使用Thread.Join,如果你想等到线程终止。如果没有及时,你可以打电话给Abort。

在您的情况下,您应该真正将加载项加载到单独的AppDomain中,并在完成后卸载它。您可能希望构建一个模型,在该模型中,当它们即将关闭时,您也会发送加载项通知。

答案 3 :(得分:0)

首先,你真的应该避免使用Thread.Abort作为终止线程的方法。我不知道你是否可以控制插件的实现,但是如果你应该重新考虑那个设计。 Read thisthis,了解与Thread.Abort相关的问题的详细信息。

至于如何让其他线程停止插件创建,再次 - 你想在你的代码和插件之间设计一个接口,优雅地通知插件你希望它停止它正在做的事情。

答案 4 :(得分:0)

我知道没有办法询问线程,以获取有关谁可能声称是其所有者的线索。这基本上意味着你需要在你的插件API中添加approriate机制来关闭插件实例。也许你可以在插件界面中添加ShutdownTerminate方法,并将其作为记录合同的一部分,这些合同必须能够很好地清理他们分配的所有资源。

我能想到的唯一另一个策略(这个很糟糕的时候)是跟踪应用程序自己创建的所有线程,然后假设所有其他线程都由插件拥有。您将不得不中止所有这些线程,因为您无法将它们链接到插件的特定实例。就个人而言,这听起来像是灾难的秘诀。我只会把它作为最后的手段来探索。

答案 5 :(得分:0)

对我来说,就像你在各种程序集上调用任意方法一样,这些方法可能不是设计为在一个线程上运行,期望它们可能会被取消。
在它自己的线程上运行的插件方法至少应该处理异常并清理它自己的线程。在线程上调用Thread.Abort()时,会在该线程上抛出ThreadAbortException以终止它。

Thread.Abort()不是在正常情况下终止线程的推荐方法。更好的方法是在方法中设计一种合作方式,允许您取消它。如果这是不可能的,只要执行方法偶尔在安全点进入WaitSleepJoin状态(等待WaitHandle,休眠等),调用Thread.Interrupt()是一种更温和的终止线程的方法。在这种情况下,线程上抛出ThreadInterruptedException。其他线程仍应在异常处理程序中清理。

答案 6 :(得分:0)

其他人都是对的 - 在优雅的关机信号中编码。但是,如果您无法轻易更改子线程的代码,并且您的计划压力很大,并且如果子线程重置或挂起中止的可能性很小,并且您承诺稍后重构,那么您可以为插件添加一个故障保护,将子线程添加到集合中,然后捕获ThreadAbortException并使集合中止子线程。