19

我创建了一个运行某种方法的线程。但有时我想杀死线程,即使它仍在工作。我怎样才能做到这一点?我尝试了 Thread.Abort() 但它显示了一个消息框,上面写着“线程中止”。我应该怎么办?

4

8 回答 8

49

不要打电话Thread.Abort()

Thread.Abort很危险。相反,您应该与线程合作,以便可以和平地关闭它。需要对线程进行设计,以便可以告诉它杀死自己,例如,keepGoing当您希望线程停止时,将布尔标志设置为 false。然后线程会有类似的东西

while (keepGoing)
{
    /* Do work. */
}

如果线程可能在 a 中阻塞,Sleep那么Wait您可以通过调用将其从这些函数中分离出来Thread.Interrupt()。然后应该准备处理线程ThreadInterruptedException

try
{
    while (keepGoing)
    {
        /* Do work. */
    }
}
catch (ThreadInterruptedException exception)
{
    /* Clean up. */
}
于 2009-06-27T00:51:06.603 回答
26

你真的应该只调用 Abort() 作为最后的手段。您可以使用变量来同步此线程:

volatile bool shutdown = false;

void RunThread()
{
   while (!shutdown)
   {
      ...
   }
}

void StopThread()
{
   shutdown = true;
}

这允许你的线程干净地完成它正在做的事情,让你的应用程序处于已知的良好状态。

于 2009-06-27T00:47:51.320 回答
9

最正确和线程安全的方法是使用 WaitHandle 在应该停止时向线程发出信号。我主要使用 ManualResetEvent。

在您的线程中,您可以拥有:

private void RunThread()
{
    while(!this.flag.WaitOne(TimeSpan.FromMilliseconds(100)))
    {
        // ...
    }
}

其中this.flag是 ManualResetEvent 的一个实例。这意味着您可以this.flag.Set()从线程外部调用来停止循环。

WaitOne 方法仅在设置标志时返回 true。否则,它将在指定的超时(示例中为 100 毫秒)后超时,线程将再次运行循环。

于 2009-06-27T06:20:14.967 回答
7

杀死线程不是一个好主意。最好发出信号让它停止并让它优雅地结束。有多种不同的方法可以做到这一点。

  • Thread.Interrupt如果它被阻止,请使用它来戳它。
  • 轮询标志变量。
  • 使用WaitHandle类发送信号。

我没有必要重新讨论如何使用每种方法,因为我已经在这个答案中这样做了。

于 2010-09-20T17:39:59.780 回答
2

中止线程是一个非常糟糕的主意,因为您无法确定线程在中止时正在做什么。

相反,有一个线程可以检查的属性,并且您的外部代码可以设置。当线程在安全的地方退出时,让线程检查这个布尔属性。

于 2009-06-27T00:49:04.470 回答
2

我同意乔恩 B

volatile bool shutdown = false;

void RunThread()
{

try
{
    while (!shutdown)
    {
        /* Do work. */
    }
}
catch (ThreadAbortException exception)
{
    /* Clean up. */
}
}

void StopThread()
{
   shutdown = true;
}
于 2012-05-19T11:55:38.167 回答
1

在我的 WebServer 类中也有杀死线程的例子......

https://net7ntcip.codeplex.com/SourceControl/changeset/view/89621#1752948

我想说 Abort 没问题,只要了解后果是什么……只要您在长时间运行的任务 Abort 将起作用之前指示状态,但需要标志,例如(ShouldStop 或 ActionBranch 等)

查看示例!

于 2012-05-19T11:59:18.040 回答
0

编辑:

  1. 我为此创建了一个小类

  2. 注意到它不适用于 async/await

  3. 向班级发布了更新,然后 Theodor Zoulias(谢谢 :))让我知道这个想法是有缺陷的。

  4. 现在我正在重新发布原始课程(不适用于 async/await!)

    var t = new StopAbleThread(isShutDown =>
     {
       Console.WriteLine("a");
       while (!isShutDown())
       {
         Console.WriteLine("b");
         Thread.Sleep(TimeSpan.FromMinutes(10));
       }
     }  )   
    
    { IsBackground = true };
       t.Start( );
    

像这样停止线程:

t.Stop();

班上:

public class StopAbleThread
{
  public bool IsBackground
  {
    set => _thread.IsBackground = value;
  }

  private readonly Thread _thread;
  private volatile bool _shutdown;

  public delegate bool IsShutDown( );
  public delegate void CodeToRun( IsShutDown isShutDown );


  public StopAbleThread( CodeToRun codeToRun )
  {
    _thread = new Thread( ( ) =>
    {
      try
      {
        codeToRun( _IsShutDown );
      }
      catch( ThreadInterruptedException )
      {
        //ignore
      }
    } );
  }

  private bool _IsShutDown( )
  {
    return _shutdown;
  }

  public void Start( )
  {
    _thread.Start( );
  }

  public void Stop( )
  {
    _shutdown = true;
    _thread.Interrupt( );
  }
}
于 2021-07-16T09:37:22.890 回答