首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在ThreadPool中的线程上调用Thread.Abort

在ThreadPool中的线程上调用Thread.Abort
EN

Stack Overflow用户
提问于 2010-02-25 23:36:44
回答 4查看 12K关注 0票数 18

我的同事正在使用第三方.NET库,我们没有源代码。我们使用ThreadPool来让很多线程调用这个库,偶尔会有一个线程永远挂起,而其他线程则兴高采烈地向前推进。

所以我们想使用可怕的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);
}

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

编辑:我非常清楚Thread.Abort的所有潜在问题。我知道最好不要在生产代码中使用它,它甚至不一定要停止线程,如果你在线程获得锁的时候中止线程,那么你可以挂起其他线程,等等。但是现在我们的最后期限很紧,我们有充分的理由相信在这个特定的情况下,我们可以在不危及整个进程的情况下调用Thread.Abort,并且我们希望避免重写这个程序来消除ThreadPool,除非万不得已。

所以我想知道的是:假设我们将在属于ThreadPool的线程上调用Thread.Abort,这些ThreadPool线程是否会导致任何特殊的问题,我们是否必须手动启动一个新线程来替换被杀死的线程,或者ThreadPool会为我们做这件事?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-02-25 23:40:52

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

调用你不信任的函数的正确方法是在一个新的进程中启动它,并在必要时终止该进程。

票数 8
EN

Stack Overflow用户

发布于 2010-02-26 00:01:40

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

因此,虽然通常不建议中止线程,但有些主机在中止线程时非常激进。其中之一就是ASP.NET,当一个请求耗时太长时,它会为你中止线程。因此,考虑到这一点,说“永远不要中止线程”是愚蠢的。

我建议您找出这段代码挂在哪里( ThreadAbortException的堆栈跟踪应该会给您提供很多信息)。如果它总是挂在同一个地方(可能是死锁),用Reflector找出在这一点上中止线程是否会导致某种状态损坏。有了这些信息,您可能已经可以修复问题(也许您锁定了该库的某个对象),或者可以向该库的作者发送一封邮件。如果所有这些都不起作用,并且您认为中止它没有风险,请务实地将其扼杀:-)

但是,如果有任何状态损坏的变化,您应该尝试遵循Mark Byer的答案。也就是说:尝试在它自己的AppDomain中运行库。通过这种方式,您可以卸载完整的AppDomain,其中的更改不会影响您的应用程序。

票数 7
EN

Stack Overflow用户

发布于 2010-07-09 02:43:07

请阅读斯蒂芬·图布的“'Abortable Thread Pool'”。他提供了一个可中止线程池的源代码。这是一本有趣的读物。

在线程池排队时,他调用自己的回调'HandleItem‘。在“HandleItem”中,在将当前线程添加到其包装器类中的字典列表之后,他将执行实际的回调。

ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem));

HandleItem(...) {
...
_threads.Add(item, Thread.CurrentThread);
...
}

他使用字典将他的WorkItems链接到线程,当用户想要取消一个线程时,它会查找并取消那个特定的线程。

Dictionary<WorkItem, Thread>() _threads = New Dictionary<WorkItem, Thread>();

http://msdn.microsoft.com/en-us/magazine/cc163644.aspx

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2335238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档