Pausing and Resuming Threads

After you have started a thread, you often want to pause that thread for a fixed period of time. Calling Thread.Sleep causes the current thread to immediately block for the number of milliseconds you pass to Sleep, yielding the remainder of its time slice to another thread. One thread cannot call Sleep on another thread. Calling Thread.Sleep(Timeout.Infinite) causes a thread to sleep until it is interrupted by another thread that calls Thread.Interrupt or is aborted by Thread.Abort.

You can also pause a thread by calling Thread.Suspend. When a thread calls Thread.Suspend on itself, the call blocks until the thread is resumed by another thread. When one thread calls Thread.Suspend on another thread, the call is a nonblocking call that causes the other thread to pause. Calling Thread.Resume breaks another thread out of the suspend state and causes the thread to resume execution, regardless of how many times Thread.Suspend was called. For example, if you call Thread.Suspend five consecutive times and then call Thread.Resume, the thread resumes execution immediately following the call to Resume.

Unlike Thread.Sleep, Thread.Suspend does not cause a thread to immediately stop execution. The common language runtime must wait until the thread has reached a safe point before it can suspend the thread. A thread cannot be suspended if it has not been started or if it has stopped. For details on safe points, see Thread.Suspend, Garbage Collection, and Safe Points.

The Suspend and Resume methods are not generally useful for applications, and should not be confused with synchronization mechanisms. Because Suspend and Resume do not rely on the cooperation of the thread being controlled, they are highly intrusive and can result in serious application problems like deadlocks (for example, if you suspend a thread that holds a resource that another thread will need). Some applications do need to control the priority of threads for better performance. To do this, you should use Thread.Priority rather than Thread.Suspend.

You can block threads in a number of ways. For example, you can have a thread wait for another thread to stop by calling Thread.Join. You can have a thread wait for access to a synchronized object using Monitor.Wait, or you can put it to sleep using Thread.Sleep. You can interrupt a waiting thread by calling Thread.Interrupt on the blocked thread to throw a ThreadInterruptedException, which breaks the thread out of the blocking call. The thread should catch the ThreadInterruptedException and do whatever is appropriate to continue working. If the thread ignores the exception, the runtime catches the exception and stops the thread.

If a wait is a managed wait, then Thread.Interrupt and Thread.Abort both wake the thread immediately. If a wait is an unmanaged wait (for example, a platform invoke call to the Win32 WaitForSingleObject function), neither Interrupt nor Abort can take control of the thread until it returns to or calls into managed code. In managed code:

  • Thread.Interrupt wakes a thread out of any wait it might be in and causes a ThreadInterruptedException to be thrown in the destination thread.
  • Thread.Abort is similar to Thread.Interrupt, except that it causes ThreadAbortException to be thrown on the thread. For details, see Destroying Threads.

See Also

Threading | Using Threads and Threading | Thread | ThreadInterruptedException | ThreadAbortException | Thread.Suspend, Garbage Collection, and Safe Points