Anhalten und Unterbrechen von Threads
Die gängigsten Verfahren zum Synchronisieren der Aktivitäten von Threads bestehen darin, Threads zu blockieren und freizugeben bzw. Objekte oder Codebereiche zu sperren. Weitere Informationen zu diesen Sperr- und Blockierungsmechanismen finden Sie unter Übersicht über Synchronisierungsprimitiven.
Sie können auch vorsehen, dass Threads sich selbst deaktivieren (in den Standbymodus versetzen). Wenn Threads blockiert oder deaktiviert sind, können Sie sie mit einer ThreadInterruptedException wieder aus ihrem Wartezustand holen.
Die „Thread.Sleep“-Methode
Durch Aufrufen der Thread.Sleep-Methode wird der aktuelle Thread sofort für die in Millisekunden angegebene Dauer oder das Zeitintervall, das Sie an die Methode übergeben, blockiert, wobei das restliche Zeitsegment dieses Threads einem anderen Thread zur Verfügung gestellt wird. Nachdem dieses Intervall abgelaufen ist, setzt der pausierte Thread die Ausführung fort.
Ein Thread kann Thread.Sleep nicht für einen anderen Thread aufrufen. Thread.Sleep ist eine statische Methode, die immer den aktuellen Thread in den Standbymodus versetzt.
Durch den Aufruf von Thread.Sleep mit einem Wert von Timeout.Infinite verbleibt ein Thread so lange im Standbymodus, bis er von einem anderen Thread unterbrochen wird, der die Thread.Interrupt-Methode für den im Standbymodus befindlichen Thread aufruft, oder bis er durch einen Aufruf seiner Thread.Abort-Methode beendet wird. Im folgenden Beispiel werden beide Methoden zum Unterbrechen des Standbymodus eines Threads veranschaulicht.
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.
Unterbrechen von Threads
Sie können einen wartenden Thread unterbrechen, indem Sie die Thread.Interrupt-Methode für den blockierten Thread aufrufen, um eine ThreadInterruptedException auszulösen, durch die der Thread aus dem blockierenden Aufruf gelöst wird. Der Thread sollte die ThreadInterruptedException abfangen und die angemessenen Aktionen zum Fortsetzen der Arbeit ausführen. Wenn der Thread die Ausnahme ignoriert, wird diese von der Laufzeit abgefangen, und der Thread wird beendet.
Hinweis
Wenn der Zielthread beim Aufrufen von Thread.Interrupt nicht blockiert ist, muss er zuerst blockiert werden, bevor er unterbrochen werden kann. Wenn der Thread nie blockiert wird, kann er ohne jegliche Unterbrechung abgeschlossen werden.
Wenn sich ein Thread in einem verwalteten Wartezustand befindet, kann er durch Thread.Interrupt und Thread.Abort sofort aktiviert werden. Bei einem nicht verwalteten Wartezustand (beispielsweise bei einem Plattformaufruf der Win32-WaitForSingleObject-Funktion) können Thread.Interrupt und Thread.Abort die Steuerung des Threads erst übernehmen, wenn der Thread zu verwaltetem Code zurückkehrt oder einen Aufruf in verwaltetem Code ausführt. In verwaltetem Code sieht das Verhalten wie folgt aus:
Thread.Interrupt aktiviert einen Thread aus jedem Wartezustand heraus und veranlasst, dass eine ThreadInterruptedException im Zielthread ausgelöst wird.
Nur .NET Framework: Thread.Abort aktiviert einen Thread aus einem beliebigen Wartezustand heraus und veranlasst das Auslösen einer ThreadAbortException für den Thread. Ausführliche Informationen finden Sie unter Zerstören von Threads.