[ACCEPTED]-Is there a way to indefinitely pause a thread?-multithreading

Accepted answer
Score: 96

Never, ever use Thread.Suspend. The major problem with 38 it is that 99% of the time you can't know 37 what that thread is doing when you suspend 36 it. If that thread holds a lock, you make 35 it easier to get into a deadlock situation, etc. Keep 34 in mind that code you are calling may be 33 acquiring/releasing locks behind the scenes. Win32 32 has a similar API: SuspendThread and ResumeThread. The following 31 docs for SuspendThread give a nice summary of the dangers 30 of the API:

http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx

This function is primarily designed 29 for use by debuggers. It is not intended 28 to be used for thread synchronization. Calling 27 SuspendThread on a thread that owns a synchronization 26 object, such as a mutex or critical section, can 25 lead to a deadlock if the calling thread 24 tries to obtain a synchronization object 23 owned by a suspended thread. To avoid this 22 situation, a thread within an application 21 that is not a debugger should signal the 20 other thread to suspend itself. The target 19 thread must be designed to watch for this 18 signal and respond appropriately.

The proper 17 way to suspend a thread indefinitely is 16 to use a ManualResetEvent. The thread is most likely looping, performing 15 some work. The easiest way to suspend the 14 thread is to have the thread "check" the 13 event each iteration, like so:

while (true)
{
    _suspendEvent.WaitOne(Timeout.Infinite);

    // Do some work...
}

You specify 12 an infinite timeout so when the event is 11 not signaled, the thread will block indefinitely, until 10 the event is signaled at which point the 9 thread will resume where it left off.

You 8 would create the event like so:

ManualResetEvent _suspendEvent = new ManualResetEvent(true);

The true parameter 7 tells the event to start out in the signaled 6 state.

When you want to pause the thread, you 5 do the following:

_suspendEvent.Reset();

And to resume the thread:

_suspendEvent.Set();

You 4 can use a similar mechanism to signal the 3 thread to exit and wait on both events, detecting 2 which event was signaled.

Just for fun I'll 1 provide a complete example:

public class Worker
{
    ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    ManualResetEvent _pauseEvent = new ManualResetEvent(true);
    Thread _thread;

    public Worker() { }

    public void Start()
    {
        _thread = new Thread(DoWork);
        _thread.Start();
    }

    public void Pause()
    {
        _pauseEvent.Reset();
    }

    public void Resume()
    {
        _pauseEvent.Set();
    }

    public void Stop()
    {
        // Signal the shutdown event
        _shutdownEvent.Set();

        // Make sure to resume any paused threads
        _pauseEvent.Set();

        // Wait for the thread to exit
        _thread.Join();
    }

    public void DoWork()
    {
        while (true)
        {
            _pauseEvent.WaitOne(Timeout.Infinite);

            if (_shutdownEvent.WaitOne(0))
                break;

            // Do the work here..
        }
    }
}
Score: 16

The Threading in C# ebook summarises Thread.Suspend and 5 Thread.Resume thusly:

The deprecated Suspend 4 and Resume methods have two modes – dangerous 3 and useless!

The book recommends using a 2 synchronization construct such as an AutoResetEvent or 1 Monitor.Wait to perform thread suspending and resuming.

Score: 2

If there are no synchronization requirements:

Thread.Sleep(Timeout.Infinite);

0

Score: 1

I just implemented a LoopingThread class which loops 11 an action passed to the constructor. It 10 is based on Brannon's post. I've put some 9 other stuff into that like WaitForPause(), WaitForStop(), and a TimeBetween property, that 8 indicates the time that should be waited 7 before next looping.

I also decided to change 6 the while-loop to an do-while-loop. This 5 will give us a deterministic behavior for 4 a successive Start() and Pause(). With deterministic I 3 mean, that the action is executed at least 2 once after a Start() command. In Brannon's implementation 1 this might not be the case.

I omitted some things for the root of the matter. Things like "check if the thread was already started", or the IDisposable pattern.

public class LoopingThread
{
  private readonly Action _loopedAction;
  private readonly AutoResetEvent _pauseEvent;
  private readonly AutoResetEvent _resumeEvent;
  private readonly AutoResetEvent _stopEvent;
  private readonly AutoResetEvent _waitEvent;

  private readonly Thread _thread;

  public LoopingThread (Action loopedAction)
  {
    _loopedAction = loopedAction;
    _thread = new Thread (Loop);
    _pauseEvent = new AutoResetEvent (false);
    _resumeEvent = new AutoResetEvent (false);
    _stopEvent = new AutoResetEvent (false);
    _waitEvent = new AutoResetEvent (false);
  }

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

  public void Pause (int timeout = 0)
  {
    _pauseEvent.Set();
    _waitEvent.WaitOne (timeout);
  }

  public void Resume ()
  {
    _resumeEvent.Set ();
  }

  public void Stop (int timeout = 0)
  {
    _stopEvent.Set();
    _resumeEvent.Set();
    _thread.Join (timeout);
  }

  public void WaitForPause ()
  {
    Pause (Timeout.Infinite);
  }

  public void WaitForStop ()
  {
    Stop (Timeout.Infinite);
  }

  public int PauseBetween { get; set; }

  private void Loop ()
  {
    do
    {
      _loopedAction ();

      if (_pauseEvent.WaitOne (PauseBetween))
      {
        _waitEvent.Set ();
        _resumeEvent.WaitOne (Timeout.Infinite);
      }
    } while (!_stopEvent.WaitOne (0));
  }
}
Score: 0

Beside suggestions above, I'd like to add 4 one tip. In some cases, use BackgroundWorker 3 can simplify your code (especially when 2 you use anonymous method to define DoWork 1 and other events of it).

Score: 0

In line with what the others said - don't 13 do it. What you really want to do is to 12 "pause work", and let your threads roam 11 free. Can you give us some more details 10 about the thread(s) you want to suspend? If 9 you didn't start the thread, you definitely 8 shouldn't even consider suspending it - its 7 not yours. If it is your thread, then I 6 suggest instead of suspending it, you just 5 have it sit, waiting for more work to do. Brannon 4 has some excellent suggestions for this 3 option in his response. Alternatively, just 2 let it end; and spin up a new one when you 1 need it.

More Related questions