杀死.NET线程

时间:2009-06-27 00:38:10

标签: c# multithreading abort

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

8 个答案:

答案 0 :(得分:48)

Do not call Thread.Abort()!

Thread.Abort很危险。相反,你应该与线程合作,以便它可以安静地关闭。需要设计线程,以便可以告诉它自杀,例如,当你想让线程停止时,你设置一个布尔keepGoing标志。然后该线程将具有类似

的内容
while (keepGoing)
{
    /* Do work. */
}

如果该帖子可能会在SleepWait中阻止,那么您可以通过调用Thread.Interrupt()将其从这些功能中删除。然后应该准备线程来处理ThreadInterruptedException

try
{
    while (keepGoing)
    {
        /* Do work. */
    }
}
catch (ThreadInterruptedException exception)
{
    /* Clean up. */
}

答案 1 :(得分:25)

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

volatile bool shutdown = false;

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

void StopThread()
{
   shutdown = true;
}

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

答案 2 :(得分:9)

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

在你的主题中,你可以:

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

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

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

答案 3 :(得分:7)

杀死一个帖子不是一个好主意。最好发出信号表示它应该停止并让它优雅地结束。有各种不同的方法可以做到这一点。

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

我没有必要重新讨论每种方法的使用方法,因为我已经在this answer中这样做了。

答案 4 :(得分:2)

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

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

答案 5 :(得分:2)

我同意Jon B

volatile bool shutdown = false;

void RunThread()
{

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

void StopThread()
{
   shutdown = true;
}

答案 6 :(得分:1)

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

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

我想说Abort是可以的,只要了解后果是什么......只要你在长时间运行任务之前指示状态Abort会工作但是需要标志,如(ShouldStop或ActionBranch等)

查看示例!

答案 7 :(得分: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( );
  }
}