Приостановка и прерывание потоковPausing and interrupting threads

Наиболее распространенными способами синхронизации действий потоков являются блокировка и освобождение потоков или блокировка объектов или областей кода.The most common ways to synchronize the activities of threads are to block and release threads, or to lock objects or regions of code. Подробнее об этих механизмах фиксации и блокировки см. в разделе Обзор примитивов синхронизации.For more information on these locking and blocking mechanisms, see Overview of Synchronization Primitives.

Также можно организовать перевод потоков в спящий режим.You can also have threads put themselves to sleep. Если потоки заблокированы или находятся в спящем режиме, можно использовать ThreadInterruptedException для вывода потоков из состояния ожидания.When threads are blocked or sleeping, you can use a ThreadInterruptedException to break them out of their wait states.

Метод Thread.SleepThe Thread.Sleep method

Вызов метода Thread.Sleep приводит к немедленной блокировке текущего потока на определенное количество миллисекунд, переданное этому методу, вследствие чего остаток среза времени передается другому потоку.Calling the Thread.Sleep method causes the current thread to immediately block for the number of milliseconds or the time interval you pass to the method, and yields the remainder of its time slice to another thread. По истечении этого интервала времени спящий поток возобновляет выполнение.Once that interval elapses, the sleeping thread resumes execution.

Поток не может вызвать метод Thread.Sleep для другого потока.One thread cannot call Thread.Sleep on another thread. Статический метод Thread.Sleep всегда переводит текущий поток в спящий режим.Thread.Sleep is a static method that always causes the current thread to sleep.

Вызов метода Thread.Sleep с аргументом Timeout.Infinite переводит поток в спящий режим до того момента, пока он не будет прерван другим потоком путем вызова метода Thread.Interrupt или завершен путем вызова метода Thread.Abort.Calling Thread.Sleep with a value of Timeout.Infinite causes a thread to sleep until it is interrupted by another thread that calls the Thread.Interrupt method on the sleeping thread, or until it is terminated by a call to its Thread.Abort method. В следующем примере показаны оба метода прерывания спящего потока.The following example illustrates both methods of interrupting a sleeping thread.

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Interrupt a sleeping thread. 
      var sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Interrupt();
      
      Thread.Sleep(1000);
      
      sleepingThread = new Thread(Example.SleepIndefinitely);
      sleepingThread.Name = "Sleeping2";
      sleepingThread.Start();
      Thread.Sleep(2000);
      sleepingThread.Abort();
   }

   private static void SleepIndefinitely()
   {
      Console.WriteLine("Thread '{0}' about to sleep indefinitely.",
                        Thread.CurrentThread.Name);
      try {
         Thread.Sleep(Timeout.Infinite);
      }
      catch (ThreadInterruptedException) {
         Console.WriteLine("Thread '{0}' awoken.",
                           Thread.CurrentThread.Name);
      }
      catch (ThreadAbortException) {
         Console.WriteLine("Thread '{0}' aborted.",
                           Thread.CurrentThread.Name);
      }
      finally 
      {
         Console.WriteLine("Thread '{0}' executing finally block.", 
                           Thread.CurrentThread.Name);
      }
      Console.WriteLine("Thread '{0} finishing normal execution.", 
                        Thread.CurrentThread.Name);
      Console.WriteLine();
   }
}
// The example displays the following output:
//       Thread 'Sleeping' about to sleep indefinitely.
//       Thread 'Sleeping' awoken.
//       Thread 'Sleeping' executing finally block.
//       Thread 'Sleeping finishing normal execution.
//       
//       Thread 'Sleeping2' about to sleep indefinitely.
//       Thread 'Sleeping2' aborted.
//       Thread 'Sleeping2' executing finally block.
Imports System.Threading

Module Example
   Public Sub Main()
      ' Interrupt a sleeping thread. 
      Dim sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
      sleepingThread.Name = "Sleeping"
      sleepingThread.Start()
      Thread.Sleep(2000)
      sleepingThread.Interrupt()
      
      Thread.Sleep(1000)
      
      sleepingThread = New Thread(AddressOf Example.SleepIndefinitely)
      sleepingThread.Name = "Sleeping2"
      sleepingThread.Start()
      Thread.Sleep(2000)
      sleepingThread.Abort()
   End Sub

   Private Sub SleepIndefinitely()
      Console.WriteLine("Thread '{0}' about to sleep indefinitely.",
                        Thread.CurrentThread.Name)
      Try 
         Thread.Sleep(Timeout.Infinite)
      Catch ex As ThreadInterruptedException
         Console.WriteLine("Thread '{0}' awoken.",
                           Thread.CurrentThread.Name)
      Catch ex As ThreadAbortException
         Console.WriteLine("Thread '{0}' aborted.",
                           Thread.CurrentThread.Name)
      Finally 
         Console.WriteLine("Thread '{0}' executing finally block.", 
                           Thread.CurrentThread.Name)
      End Try
      Console.WriteLine("Thread '{0} finishing normal execution.", 
                        Thread.CurrentThread.Name)
      Console.WriteLine()
   End Sub
End Module
' The example displays the following output:
'       Thread 'Sleeping' about to sleep indefinitely.
'       Thread 'Sleeping' awoken.
'       Thread 'Sleeping' executing finally block.
'       Thread 'Sleeping finishing normal execution.
'       
'       Thread 'Sleeping2' about to sleep indefinitely.
'       Thread 'Sleeping2' aborted.
'       Thread 'Sleeping2' executing finally block.

Прерывание потоковInterrupting threads

Ожидающий поток можно прервать, вызвав метод Thread.Interrupt для заблокированного потока. Это действие создает исключение ThreadInterruptedException, которое выводит поток из вызова блокировки.You can interrupt a waiting thread by calling the Thread.Interrupt method on the blocked thread to throw a ThreadInterruptedException, which breaks the thread out of the blocking call. Поток должен перехватить исключение ThreadInterruptedException и выполнить соответствующие действия для продолжения работы.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.

Примечание

Если целевой поток не заблокирован при вызове метода Thread.Interrupt, поток не прерывается до блокировки.If the target thread is not blocked when Thread.Interrupt is called, the thread is not interrupted until it blocks. Если поток никогда не блокируется, он может завершиться, не будучи прерванным.If the thread never blocks, it could complete without ever being interrupted.

Если ожидание является управляемым, методы Thread.Interrupt и Thread.Abort незамедлительно выводят поток из спящего режима.If a wait is a managed wait, then Thread.Interrupt and Thread.Abort both wake the thread immediately. Если ожидание является неуправляемым (как, например, вызов неуправляемого кода функции Win32 WaitForSingleObject), то методы Thread.Interrupt и Thread.Abort не могут управлять потоком, пока он не вернется в управляемый код или не вызовет управляемый код.If a wait is an unmanaged wait (for example, a platform invoke call to the Win32 WaitForSingleObject function), neither Thread.Interrupt nor Thread.Abort can take control of the thread until it returns to or calls into managed code. В управляемом коде это поведение выглядит следующим образом:In managed code, the behavior is as follows:

См. такжеSee also