Suspension et interruption de threads

Les méthodes les plus courantes permettant de synchroniser les activités de threads consistent à bloquer et à diffuser des threads, ou à verrouiller des objets ou des régions du code. Pour plus d’informations sur ces mécanismes de verrouillage et de blocage, voir Vue d’ensemble des primitives de synchronisation.

Vous pouvez également avoir des threads en veille. Quand des threads sont bloqués ou en veille, vous pouvez utiliser une ThreadInterruptedException pour les débloquer ou les réveiller.

La méthode Thread.Sleep

L'appel de la méthode Thread.Sleep entraîne le blocage immédiat du thread actuel pendant le nombre de millisecondes ou l’intervalle de temps que dure le passage à la méthode et cède le reste de sa tranche horaire à un autre thread. Une fois l’intervalle expiré, l’exécution du thread en veille reprend.

Un thread ne peut pas appeler Thread.Sleep sur un autre thread. Thread.Sleep est une méthode statique qui entraîne systématiquement la mise en veille du thread actuel.

L’appel de Thread.Sleep avec la valeur Timeout.Infinite entraîne la mise en veille d’un thread jusqu’à ce qu’il soit interrompu par un autre thread qui appelle la méthode Thread.Interrupt ou jusqu’à ce qu’il soit arrêté par un appel à sa méthode Thread.Abort. L’exemple suivant illustre les deux méthodes d’interruption d’un thread en veille.

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.

Interruption de threads

Vous pouvez interrompre un thread en attente en appelant la méthode Thread.Interrupt sur le thread bloqué pour lever une ThreadInterruptedException, ce qui retirera le thread de l'appel bloquant. Le thread doit intercepter la ThreadInterruptedException et faire tout le nécessaire pour continuer à fonctionner. Si le thread ignore l'exception, le runtime intercepte l'exception et arrête le thread.

Notes

Si le thread cible n'est pas bloqué quand Thread.Interrupt est appelé, le thread ne sera pas interrompu avant d'être bloqué. Si le thread n'est jamais bloqué, il peut se terminer sans jamais être interrompu.

En cas d'attente managée, Thread.Interrupt et Thread.Abort réveillent le thread immédiatement. En cas d'attente non managée (par exemple, dans le cas d'un appel de code non managé à la fonction Win32 WaitForSingleObject ), ni Thread.Interrupt ni Thread.Abort ne pourront prendre le contrôle du thread tant qu'il ne sera pas retourné dans du code managé ou tant qu'il n'effectuera pas d'appel depuis du code managé. Dans du code managé, le comportement est le suivant :

Voir aussi