如何在 C# 中立即杀死一个线程?

Posted

技术标签:

【中文标题】如何在 C# 中立即杀死一个线程?【英文标题】:How to kill a thread instantly in C#? 【发布时间】:2010-11-22 13:30:28 【问题描述】:

我正在使用thread.Abort 方法杀死线程,但它不起作用。有没有其他方法可以终止线程?

private void button1_Click(object sender, EventArgs e)

    if (Receiver.IsAlive == true)
    
        MessageBox.Show("Alive");
        Receiver.Abort();
    
    else
    
        MessageBox.Show("Dead");
        Receiver.Start();
    

我正在使用它,但每次获得Alive 状态时,Receiver 都是我的全局线程。

【问题讨论】:

危险,威尔罗宾逊,危险! 非常不要使用 Thread.Abort - 几乎总是一个坏主意。 那应该用什么来杀死线程呢? 要求线程停止,从那一刻起忽略线程。 如果您绝对必须将其关闭一个运行任意的、可能对被删除的代码怀有敌意的线程,那么唯一合理安全且有效的方法就是隔离该线程线程进入自己的进程。无法保证线程中止会成功,但您应该能够取消进程。 要添加到这个(旧)问题的 cmets,这里是一个相关的(旧)问题:“What's wrong with using Thread.Abort()”。 【参考方案1】:

之所以很难杀死一个线程,是因为语言设计者希望避免以下问题:您的线程获得了一个锁,然后在它释放之前杀死它。现在任何需要那个锁的人都会被卡住。

你要做的是使用一些全局变量来告诉线程停止。您必须在您的线程代码中手动检查该全局变量并在您看到它表明您应该停止时返回。

【讨论】:

我自己使用这个机制。对于基于 UI 的代码,我设置了一个全局变量,对于服务,我检查了一个数据库表。不错且可预测。 如果可能,请使用 ManualResetEvent 而不是变量,这是它们的设计目的。 我现在很好奇 - ManualResetEvent 如何更好地检查提前终止条件?我知道当我们必须阻止某些东西时它们会更好,但这里没有阻止。 基本上我同意,但在非常特殊的情况下(您有一个线程不需要与其他线程同步 - 然后您可以在下面查看我的解决方案)。 我更喜欢Adrian Regan's answer,其中包含用于告诉线程它应该停止的代码(interrupt),然后如果线程未能在商定的时间内停止,最后求助到abort【参考方案2】:

你可以通过这种方式立即杀死:

private Thread _myThread = new Thread(SomeThreadMethod);

private void SomeThreadMethod()

   // do whatever you want


[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
private void KillTheThread()

   _myThread.Abort();

我总是使用它并为我工作:)

【讨论】:

但请参阅 ***.com/a/1560567/199364,以及其他描述 thread.abort 有风险的答案。 Adrian Regan's answer 是一种更安全的使用Abort 的方法——如果线程没有死,作为最后的手段。 不,它不会杀死线程,您可以使用do while 测试自己【参考方案3】:

你应该首先有一些商定的结束线程的方法。例如线程可以检查和遵守的 running_ 变量。

您的主线程代码应该包含在一个异常块中,该块捕获 ThreadInterruptException 和 ThreadAbortException,这将在退出时干净地整理线程。

在 ThreadInterruptException 的情况下,您可以检查 running_ 变量以查看是否应该继续。对于 ThreadAbortException 的情况,您应该立即整理并退出线程过程。

尝试停止线程的代码应该执行以下操作:

running_ = false;
threadInstance_.Interrupt();
if(!threadInstance_.Join(2000))  // or an agreed resonable time
   threadInstance_.Abort();

【讨论】:

从我的角度来看,这是唯一可以接受的答案。是的,您首先需要一个变量来记录线程何时退出,但如果您在线程内部阻塞,您可能永远没有机会检查该变量。需要另一种方法来中断被阻塞的线程,这个答案解决了我的问题。谢谢! 如果threadInstance_.Interrupt()快速结束线程,threadInstance_.Join会抛出System.Threading.ThreadStateException: Thread has not been started 我想知道我可以将中断与不实现 CancellationToken 的 puppeteer-sharp 一起使用吗? 这实际上不起作用,threadInstance_ 继续工作【参考方案4】:

线程完成工作后会被杀死,所以如果你使用循环或其他东西,你应该将变量传递给线程以在线程完成后停止循环。

【讨论】:

【参考方案5】:

C# Thread.Abort 不能保证立即中止线程。当一个线程对自己调用 Abort 但当一个线程调用另一个线程时它可能会起作用。

请参考文档:http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

我在编写与硬件交互的工具时遇到了这个问题 - 您希望立即停止,但不能保证。我通常使用一些标志或其他此类逻辑来防止执行在线程上运行的部分代码(并且我不想在中止时执行这些代码 - 棘手)。

【讨论】:

以上是关于如何在 C# 中立即杀死一个线程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在另一个线程完成时停止一个线程

如何在新线程上运行任务并立即返回给调用者?

在 C# 中,如何可靠地杀死进程树 [重复]

While 循环计时如何在带有多个线程的 C# 中工作?

在没有服务的情况下杀死应用程序后如何在后台线程中运行代码?

如何防止主线程ios杀死后台线程