Ralph Shillington
Ralph Shillington

Reputation: 21098

Options for informing a Thread to stop

I need to inform a so-called worker thread to stop work at the next available oppertunity. Currently I'm using something like this:

    public void Run()
    {
        while (!StopRequested)
            DoWork();
    }

The concern I have is that StopRequested is being set to True on a different thread. Is this safe? I know I can't lock a boolean. Perhaps there's a different way to inform a thread that a stop is required. For example I would be happy to check Thread.CurrentThread.ThreadState == ThreadState.StopRequested but it's not clear how I can set the thread state as such.

Upvotes: 6

Views: 533

Answers (6)

Wim Coenen
Wim Coenen

Reputation: 66733

The concern I have is that StopRequested is being set to True on a different thread. Is this safe?

You should make sure that the StopRequested field has the volatile keyword. See this other answer for the reason why.

Upvotes: 1

SwDevMan81
SwDevMan81

Reputation: 49978

If you use the BackgroundWorker, you would call the CancelAsync function of the BackgroundWorker sets the CancellationPending Property to true, which is what you would look for in your loop:

public void Run(object sender, DoWorkEventArgs e)   
{      
   BackgroundWorker worker = sender as BackgroundWorker;
   if(worker != null)
   {
      while (!worker.CancellationPending)   
      {
         DoWork();  
      }
   }
}

The above would be the DoWork event code which is called when you run the RunWorkerAsync function.

Upvotes: 0

Will Eddins
Will Eddins

Reputation: 13907

You may want to look at using a BackgroundWorker to do the work for you, using RunWorkerAsync() and handling the worker.CancellationPending == true case during your logic.

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.DoWork += MyWorkFunction;
worker.RunWorkerCompleted += MyWorkDoneSuccessfullyFunction;
worker.RunWorkerAsync();

Another solution would be to use a volatile bool to signal that you need to stop, which you could set anywhere within the class.

private volatile bool cancelWork = false;

public void CancelWork()
{
  cancelWork = true;
}

Upvotes: 3

Charlie
Charlie

Reputation: 9108

You could use Thread.Abort() and wrap any necessary cleanup in the DoWork() method in a finally block.

Upvotes: 2

Reed Copsey
Reed Copsey

Reputation: 564413

This is a better approach than trying to set the ThreadState. If you look at the docs for ThreadState, it specifically says that StopRequested is for internal use only.

Setting a boolean from another thread is a safe operation. You shouldn't need to lock in this case.

Upvotes: 3

EFraim
EFraim

Reputation: 13028

Using Event object will be better probably. Especially if your thread blocks. (Then you can still wait for the event inside the blocking call)

Upvotes: 2

Related Questions