从ThreadPool调用线程上的Thread.Abort

Eli*_*ght 18 .net c# threadpool

我的同事正在使用我们没有源代码的第三方.NET库.我们正在使用ThreadPool让很多线程调用到这个库中,偶尔其中一个线程将永远挂起,而其余的线程会随意地突然出现.

所以我们想用dreaded Thread.Abort来杀死这样的线程.在我自己创建线程之前我已经完成了这个,但我从未使用过ThreadPool.如果我们跟踪每个任务的开始时间,如下所示:

static Dictionary<Thread, DateTime> started = new Dictionary<Thread, DateTime>();

static void DoSomeWork(object foo)
{
    lock(started)
        started[Thread.CurrentThread] = DateTime.Now;

    SomeBuggyLibraryThatMightInfiniteLoopOrSomething.callSomeFunction(doo);

    lock(started)
        started.Remove(Thread.CurrentThread);
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以锁定并迭代正在运行的线程并调用Thread.Abort以杀死它们吗?如果我们这样做,那么我们是否需要向ThreadPool添加一个新线程来替换我们刚刚杀死的线程,或者ThreadPool会为我们处理它?

编辑:我非常清楚所有潜在的问题Thread.Abort.我知道理想情况下它应该永远不会在生产代码中使用,并且它不一定会停止线程,并且如果你在线程获得锁定时中止线程,那么你可以挂断其他线程等.但是现在我们是在时间紧,我们有体面的理由相信,在这一特定情况下,我们可以调用Thread.Abort没有把整个过程处于危险之中,我们想避免重写这个程序,以消除线程池,除非我们绝对必须.

所以我想知道的是这样的:因为我们将调用Thread.Abort上属于一个线程池线程,有没有引起这些是线程池线程的任何特殊问题,做我们必须手动旋转了一个新的线程来代替一个被杀的人还是ThreadPool会为我们做的?

Mar*_*ers 9

不,你不应该在线程池中的线程上调用Abort.从我的本地测试来看,似乎ThreadPool确实会重新创建线程,如果你中止它们 - 我中止了1000个线程池线程并且它仍在工作.我不知道你是否应该依赖这种行为,但也许你可以在这种情况下逃脱它.通常虽然使用Thread.Abort不是正确的方法.

调用您不信任的函数以表现良好的正确方法是在新进程中启动它并在必要时终止该进程.

  • -1.对不起,我通常不会低估任何意图很好的答案,但Eli显然*知道'Thread.Abort`是邪恶的,并且询问情况是否与线程池线程有任何不同(即更邪恶).只重复(众所周知的)'Thread.Abort`是邪恶的事实并没有帮助,它也没有回答问题(即ThreadPool线程是否会在Thread.Abort之后返回池). (15认同)
  • @Eli:您不应该在普通线程上调用Thread.Abort.首先,Thread.Abort甚至不保证终止该线程.即使它成功地中止了线程,你也不知道你留下了什么混乱或者如何清理它.你最终可能会得到不受约束的资源.这真的不是一个好主意. (5认同)
  • @Mark:我明白了你的观点,我喜欢你的编辑.-1改为+1.:-) (2认同)

Ste*_*ven 7

不建议使用Thread.Abort,因为它可能使您的应用程序处于无效状态.这样做的原因是,当要求线程中止时,可以在该第三方库中的几乎任何可能的位置引发异常.可能存在未编写的代码段以能够应对这些异步中止.

因此,虽然通常不建议中止线程,但是有些主机在中止线程方面非常积极.其中之一是ASP.NET.当请求花费太长时间时,它将为您中止该线程.所以考虑到这一点,说"永不中止线程"是愚蠢的.

我建议你找出这段代码挂起的地方(ThreadAbortException的堆栈跟踪应该给你很多信息).如果它总是挂在同一个地方(它可能是死锁),如果在该点中止一个线程将导致某些状态损坏,请找出Reflector.有了这些信息,您可能已经解决了问题(也许您锁定了该库的对象),或者可以向该库的编写者发送邮件.如果这一切都没有帮助,你看到没有中止它的风险,务实并杀死它:-)

但是,如果任何国家腐败发生变化,你应该尝试接受马克拜尔斯的回答.那就是:尝试在自己的AppDomain中运行该库.这样您就可以卸载完整的AppDomain,并且它不会影响您的应用程序.