Wstrzymywanie i przerywanie wątków

Najczęstsze sposoby synchronizowania działań wątków to blokowanie i zwalnianie wątków albo blokowanie obiektów lub regionów kodu. Aby uzyskać więcej informacji na temat tych mechanizmów blokowania i blokowania, zobacz Omówienie elementów pierwotnych synchronizacji.

Można również mieć wątki umieścić się spać. Gdy wątki są blokowane lub śpią, możesz użyć elementu , ThreadInterruptedException aby przerwać je ze stanów oczekiwania.

Metoda Thread.Sleep

Thread.Sleep Wywołanie metody powoduje natychmiastowe zablokowanie bieżącego wątku dla liczby milisekund lub interwału czasu przekazywanego do metody i zwraca resztę fragmentu czasu do innego wątku. Po upływie tego interwału wątek uśpienia wznawia wykonywanie.

Jeden wątek nie może wywołać Thread.Sleep innego wątku. Thread.Sleep jest metodą statyczną, która zawsze powoduje uśpienie bieżącego wątku.

Wywołanie Thread.Sleep z wartością powoduje uśpienie wątku Timeout.Infinite , dopóki nie zostanie przerwany przez inny wątek, który wywołuje Thread.Interrupt metodę w wątku uśpienia lub dopóki nie zostanie przerwany przez wywołanie metody Thread.Abort . Poniższy przykład ilustruje obie metody przerywania wątku uśpienia.

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.

Przerywanie wątków

Możesz przerwać wątek oczekiwania, wywołując Thread.Interrupt metodę w zablokowanym wątku, aby zgłosić ThreadInterruptedExceptionelement , który przerywa wątek z wywołania blokującego. Wątek powinien przechwytywać ThreadInterruptedException i robić wszystko, co jest właściwe, aby kontynuować pracę. Jeśli wątek ignoruje wyjątek, środowisko uruchomieniowe przechwytuje wyjątek i zatrzymuje wątek.

Uwaga

Jeśli wątek docelowy nie zostanie zablokowany po Thread.Interrupt wywołaniu, wątek nie zostanie przerwany, dopóki nie zostanie zablokowany. Jeśli wątek nigdy nie blokuje, może zakończyć się bez przerywania.

Jeśli oczekiwanie jest zarządzane, a następnie Thread.InterruptThread.Abort oba wybudzą wątek natychmiast. Jeśli oczekiwanie jest niezarządzanym oczekiwaniem (na przykład wywołanie platformy do funkcji Win32 WaitForSingleObject ), ani Thread.InterruptThread.Abort nie może przejąć kontroli nad wątkiem, dopóki nie powróci do kodu zarządzanego lub wywoła go. W kodzie zarządzanym zachowanie jest następujące:

Zobacz też