开发者

How to Cancel a Thread?

开发者 https://www.devze.com 2022-12-13 16:40 出处:网络
In case of BackgroundWorker, a cancel can be开发者_StackOverflow中文版 reported by the e.Cancel - property of the DoWork - event handler.

In case of BackgroundWorker, a cancel can be开发者_StackOverflow中文版 reported by the e.Cancel - property of the DoWork - event handler.

How can I achieve the same thing with a Thread object?


Here is a full example of one way of doing it.

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.");    
}

In short; the thread checks a bool flag, and keeps runing as long as the flag is true. I prefer this approach over calling Thread.Abort becuase it seems a bit nicer and cleaner.


Generally you do it by the thread's execute being a delegate to a method on an object, with that object exposing a Cancel property, and the long-running operation periodically chercking that property for tru to determine whether to exit.

for example

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
     }
   }
}

Then elsewhere:

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

myThread.Start();

// somewhere else
longRunning.Cancel = true;


A blocked thread can be stopped prematurely in one of two ways:

  • Thread.Interrupt

  • Thread.Abort

The main question is if the thread works on any ressources which need to be released correctly - in this case - you need to work with a property on the actual object which runs the thread.


There's Thread.Abort, which works by injecting a ThreadAbortException into the thread. It's a little risky because:

  1. Your thread can get stuck if it's executing native code at the time
  2. The code in the thread better be exception-safe, because this ThreadAbortException could happen on any line of code within it, even something innocent like i = i + 1

You're better off coding your own signalling mechanism between your GUI thread and the background thread. It's hard to recommend something without knowing what's going on inside that thread, but where I have a thread that works by waiting on some object in a loop, I use an AutoResetEvent and wait on that too.

0

精彩评论

暂无评论...
验证码 换一张
取 消