Sdílet prostřednictvím


Pozastavení a přerušení vláken

Nejběžnějšími způsoby synchronizace aktivit vláken jsou blokování a vydávání vláken nebo uzamčení objektů nebo oblastí kódu. Další informace o těchto mechanismech uzamčení a blokování najdete v tématu Přehled primitiv synchronizace.

Můžete také nechat vlákna přejít do režimu spánku. Když jsou vlákna blokována nebo spí, můžete k jejich přerušení ze stavu čekání použít ThreadInterruptedException.

Metoda Thread.Sleep

Volání metody Thread.Sleep způsobí, že aktuální vlákno se okamžitě zablokuje na počet milisekund nebo po časový interval, který metodě zadáte, a předá zbývající část svého časového řezu jinému vláknu. Jakmile tento interval uplyne, uspáné vlákno pokračuje v provádění.

Jedno vlákno nemůže volat Thread.Sleep v jiném vlákně. Thread.Sleep je statická metoda, která vždy způsobí, že aktuální vlákno spí.

Volání Thread.Sleep s hodnotou Timeout.Infinite způsobí, že vlákno bude do režimu spánku, dokud se nepřeruší jiným vláknem, které volá Thread.Interrupt metodu ve vlákně spánku, nebo dokud se neukončí voláním jeho Thread.Abort metody. Následující příklad ukazuje obě metody přerušení spící vlákno.

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 '{Thread.CurrentThread.Name}' about to sleep indefinitely.");
      try {
         Thread.Sleep(Timeout.Infinite);
      }
      catch (ThreadInterruptedException) {
         Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' awoken.");
      }
      catch (ThreadAbortException) {
         Console.WriteLine($"Thread '{Thread.CurrentThread.Name}' aborted.");
      }
      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.
//
//       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.

Přerušení vláken

Můžete přerušit čekající vlákno tím, že zavoláte metodu Thread.Interrupt na blokovaném vlákně a vyvoláte ThreadInterruptedException, což uvolní vlákno z blokujícího volání. Vlákno by mělo zachytit ThreadInterruptedException a udělat vše, aby pokračovalo v práci. Pokud vlákno tuto výjimku ignoruje, modul runtime výjimku zachytí a zastaví vlákno.

Poznámka:

Pokud cílové vlákno není blokováno, když je Thread.Interrupt voláno, vlákno není přerušeno, dokud se nezablokuje. Pokud vlákno nikdy nezablokuje, mohlo by se dokončit bez přerušení.

Pokud je čekání spravované čekání, pak Thread.Interrupt a Thread.Abort obě okamžitě probudí vlákno. Pokud je čekání nespravované čekání (například vyvolání platformy funkce Win32 WaitForSingleObject), Thread.Interrupt ani Thread.Abort nejsou schopny převzít kontrolu nad vláknem, dokud se nevrátí nebo nevyvolá spravovaný kód. Ve spravovaném kódu je chování následující:

Viz také