Thread.Abort和Thread.Interrupt是在多线程编程中常用的两个方法。 Thread.Abort方法用于强制终止一个线程的执行。当调用Thread.Abort方法时,线程会立即停止执行,并抛出一个ThreadAbortException异常。这个异常可以被捕获,但是如果不处理,线程将会被终止。 Thread.Interrupt方法用于中断一个线程的执行。当调用Thread.Interrupt方法时,线程会收到一个中断信号,但是线程是否真正中断取决于线程本身的实现。一般情况下,线程会检查是否收到中断信号,并根据需要采取相应的操作。 需要注意的是,Thread.Abort方法是一种比较粗暴的终止线程的方式,可能会导致线程的状态不一致或资源泄漏等问题。而Thread.Interrupt方法则更加优雅,它给线程一个机会去优雅地中断自己的执行。 在使用这两个方法时,需要根据具体的需求和场景选择合适的方法。如果需要强制终止线程,并且可以处理线程终止时的异常,可以使用Thread.Abort方法。如果希望线程能够优雅地中断自己的执行,并且能够处理中断信号,可以使用Thread.Interrupt方法。

25
如果我需要取消线程上的某个操作,我应该在什么时候使用Thread.AbortThread.Interrupt。我已经阅读了相关文档,但不确定在两者之间的特定情况下应该使用哪个调用。
如果有其他方法,请告诉我它的优缺点。

19
为什么你要首先想要终止一个线程?谋杀是不好的,让它自杀吧。 - CodesInChaos
难道更好的解决方案不是在线程上实际取消操作,而不是试图杀死线程吗? - Cody Gray
实际上,这与我在不同线程中提出的另一个问题有关:http://stackoverflow.com/questions/5942688/cancelling-call-to-web-service-from-application - Silverlight Student
4个回答

22
我会尽量避免使用 Thread.Abort。自 .NET 2.0 版本以来,它的行为更加安全和可预测,但仍存在一些严重的问题。大多数托管代码中的异常可以变得安全,但不是全部。例如,如果在静态构造函数处理期间触发了终止请求,则可能会出现一些微妙的问题。更不用说,非同步异常随时可能发生,使得你无法控制定义关闭点的位置。
有几种方法可以优雅地终止线程:
  • 使用 Thread.Interrupt
  • 轮询停止标志
  • 使用 WaitHandle 事件
  • 专用的API调用
我在这里讨论了这些方法:(链接)

2
如果您在非托管代码中终止线程,我相信Thread.Abort会等待直到回到托管代码。就像在finally块中的线程一样,它不会在完成finally之前终止。 - CodesInChaos
@CodeInChaos:啊...也许比我意识到的更安全。我会查一下的。 - Brian Gideon
@CodeInChaos:是的,在这里http://msdn.microsoft.com/en-us/library/74169f59.aspx的最后一段说得很清楚。好发现! - Brian Gideon
@Brian:怎么做呢?这是由别人托管的外部服务。我只知道调用一个 Web 方法 API。除了在该线程上中止或中断,我不知道还能做什么。 - Silverlight Student
"out-of-band exception"? 线程已经没有弹性带可以用来弹其他线程了? - Pharap
显示剩余3条评论

9

大部分的建议已经完成,但是这里有一个例子来说明我如何做:

    ManualResetEvent _requestTermination = new ManualResetEvent(false);
    Thread _thread;

    public void Init()
    {
        _thread = new Thread(() =>
         {

             while (!_requestTermination.WaitOne(0))
             {
                 // do something usefull

             }

         }));

        _thread.Start();
    }

    public void Dispose()
    {
        _requestTermination.Set();

        // you could enter a maximum wait time in the Join(...)
        _thread.Join();
    }

这种方式,dispose 将等待线程退出。


如果您需要在线程内部暂停一段时间,不应添加 Thread.Sleep。使用 WaitOne(delayTime)。这样,您将永远不必等待终止它。


3

我不会使用 Thread.Abort。它会在几乎任意时间引发异常。


你能详细说明一下这里的任意时间吗?它不会在调用Abort时立即终止线程吗?如果有参考链接,将有助于支持你的说法。 - Silverlight Student
它不会在finally子句内中止,在try子句内,它将直接跳转到finally,它可以被暂时捕获,但将在catch块的末尾重新抛出,并且自.NET 4以来,lock语句按预期工作。但它可能会破坏using语句。对我来说,这已足够让我永远不使用它。 - CodesInChaos

2

使用Thread.Interrupt时要小心。如果不加等待或休眠时间,线程将无法被中断。

使用Thread.Abort时要小心。如果捕获了ThreadAbortException,则该线程将在catch + finally之后终止。

(我喜欢使用这些方法向我的线程发送信号以让它知道结束时间,然后清理并退出)


2
catch 块中,您必须调用 Thread.ResetAbort()。仅为完整起见。 - Paul Kertscher
@PaulKertscher 不,你不必这样做。当你使用_Abort_时,你可以使用_ResetAbort_来拒绝中止或在catch + finally(以及循环)之后继续执行额外的代码。 - Bitterblue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接