如何取消线程?

时间:2009-12-08 08:43:47

标签: c# multithreading

如果是BackgroundWorker,则可以通过e.Cancel - 事件处理程序的DoWork - 属性报告取消。

如何使用Thread对象实现相同的目标?

4 个答案:

答案 0 :(得分:8)

以下是一种完成此方法的完整示例。

private static bool _runThread;
private static object _runThreadLock = new object();

private static void Main(string[] args)
{
    _runThread = true;
    Thread t = new Thread(() =>
    {
        Console.WriteLine("Starting thread...");
        bool _localRunThread = true;
        while (_localRunThread)
        {
            Console.WriteLine("Working...");
            Thread.Sleep(1000);
            lock (_runThreadLock)
            {
                _localRunThread = _runThread;
            }
        }
        Console.WriteLine("Exiting thread...");
    });
    t.Start();

    // wait for any key press, and then exit the app
    Console.ReadKey();

    // tell the thread to stop
    lock (_runThreadLock)
    {
        _runThread = false;
    }

    // wait for the thread to finish
    t.Join();

    Console.WriteLine("All done.");    
}

总之;线程检查bool标志,并且只要标志为true就继续运行。我更喜欢这种方法而不是调用Thread.Abort,因为它似乎更好一些,更清洁。

答案 1 :(得分:6)

通常,您通过线程的执行作为对象上方法的委托来执行此操作,该对象公开Cancel属性,并且长时间运行的操作定期将该属性用于tru以确定是否退出

例如

public class MyLongTunningTask
{
   public MyLongRunninTask() {}
   public volatile bool Cancel {get; set; }

   public void ExecuteLongRunningTask()
   {
     while(!this.Cancel)
     {
         // Do something long running.
        // you may still like to check Cancel periodically and exit gracefully if its true
     }
   }
}

然后在其他地方:

var longRunning = new MyLongTunningTask();
Thread myThread = new Thread(new ThreadStart(longRunning.ExecuteLongRunningTask));

myThread.Start();

// somewhere else
longRunning.Cancel = true;

答案 2 :(得分:-1)

可以通过以下两种方式之一提前停止被阻止的线程:

  • 了Thread.interrupt

  • Thread.Abort的

主要问题是,如果线程适用于任何需要正确释放的资源 - 在这种情况下 - 您需要使用运行该线程的实际对象的属性。

答案 3 :(得分:-1)

Thread.Abort,它通过向线程中注入ThreadAbortException来工作。这有点冒险,因为:

  1. 如果当时正在执行本机代码,您的线程可能会卡住
  2. 线程中的代码最好是异常安全的,因为ThreadAbortException可以在其中的任何代码行上发生,即使像i = i + 1
  3. 这样的无辜者也是如此

    最好在GUI线程和后台线程之间编写自己的信号机制。在不知道该线程内部发生了什么的情况下很难推荐一些东西,但是我有一个通过在循环中等待某个对象而工作的线程,我使用AutoResetEvent并等待它。