Бөлісу құралы:


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

Наиболее распространенными способами синхронизации действий потоков являются блокировка и освобождение потоков, блокировка объектов или регионов кода. Дополнительные сведения об этих механизмах запирания и блокировки см. в обзоре примитивов синхронизации.

Вы также можете поставить потоки в спящий режим. При блокировке или спящем потоке можно использовать ThreadInterruptedException, чтобы вывести их из состояния ожидания.

Метод Thread.Sleep

Вызов метода Thread.Sleep приводит к немедленному блоку текущего потока для количества миллисекунд или интервала времени, передаваемого методу, и возвращает оставшуюся часть его среза времени другому потоку. После истечения этого интервала спящий поток возобновляет выполнение.

Один поток не может вызывать Thread.Sleep в другом потоке. Thread.Sleep — это статический метод, который всегда заставляет текущий поток засыпать.

Вызов Thread.Sleep со значением Timeout.Infinite заставляет поток спать до тех пор, пока другой поток не вызовет метод Thread.Interrupt на спящем потоке. В следующем примере показано прерывание спящего потока.

using System;
using System.Threading;

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

    private static void SleepIndefinitely()
    {
        Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' about to sleep indefinitely.");
        try
        {
            Thread.Sleep(Timeout.Infinite);
        }
        catch (ThreadInterruptedException)
        {
            Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' awoken.");
        }
        finally
        {
            Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' executing finally block.");
        }
        Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' finishing normal execution.");
        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.
Imports System.Threading

Module Example
    Public Sub Main()
        ' Interrupt a sleeping thread.
        Dim sleepingThread = New Thread(AddressOf SleepIndefinitely)
        sleepingThread.Name = "Sleeping"
        sleepingThread.Start()
        Thread.Sleep(2000)
        sleepingThread.Interrupt()
        sleepingThread.Join()
    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)
        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.Join, чтобы заблокировать вызывающий поток до завершения выполнения прерванного потока.

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

Вы можете прервать ожидающий поток, вызвав метод Thread.Interrupt в блокированном потоке для генерации ThreadInterruptedException, который выводит этот поток из блокирующего вызова. Поток должен перехватывать ThreadInterruptedException и делать все, что необходимо для продолжения работы. Если поток игнорирует исключение, среда выполнения перехватывает исключение и останавливает поток.

Примечание.

Если целевой поток не блокируется при вызове Thread.Interrupt, поток не прерывается до тех пор, пока он не блокируется. Если поток никогда не блокируется, он может завершиться без прерывания.

Если ожидание управляется, то Thread.Interrupt немедленно будит поток. Если ожидание является неуправляемым (например, вызов функции платформы Win32 WaitForSingleObject), Thread.Interrupt не сможет управлять потоком, пока он не вернётся или не будет вызван в управляемом коде. В управляемом коде поведение выглядит следующим образом:

См. также