AutoResetEvent-Klasse
Assembly: mscorlib (in mscorlib.dll)
Hinweis |
|---|
| Das auf diese Klasse angewendete HostProtectionAttribute-Attribut besitzt den Resources-Eigenschaftenwert Synchronization | ExternalThreading. Das HostProtectionAttribute hat keine Auswirkungen auf Desktopanwendungen (die normalerweise durch Doppelklicken auf ein Symbol, Eingeben eines Befehls oder eines URL in einem Browser gestartet werden). Weitere Informationen finden Sie unter der HostProtectionAttribute-Klasse oder unter SQL Server-Programmierung und Hostschutzattribute. |
In .NET Framework, Version 2.0, wird AutoResetEvent von der neuen EventWaitHandle-Klasse abgeleitet. Eine AutoResetEvent-Klasse ist hinsichtlich ihrer Funktion gleichwertig mit einer EventWaitHandle-Klasse, die mit dem EventResetMode.AutoReset-Flag erstellt wird.
Hinweis |
|---|
| Anders als die AutoResetEvent-Klasse ermöglicht die EventWaitHandle-Klasse den Zugriff auf benannte Systemsynchronisierungsereignisse. |
Mit AutoResetEvent können Threads untereinander durch Signalisieren kommunizieren. Normalerweise betrifft diese Kommunikation eine Ressource, auf die Threads exklusiv zugreifen müssen.
Ein Thread wartet auf ein Signal, indem er WaitOne in AutoResetEvent aufruft. Wenn sich AutoResetEvent im nicht signalisierten Zustand befindet, wird der Thread blockiert und wartet darauf, dass der die Ressource steuernde Thread die Verfügbarkeit der Ressource durch das Aufrufen von Set signalisiert.
Der Aufruf von Set signalisiert AutoResetEvent, einen wartenden Thread freizugeben. AutoResetEvent verbleibt im signalisierten Zustand, bis ein einzelner wartender Thread freigegeben wird, und wechselt dann automatisch in den nicht signalisierten Zustand zurück. Wenn sich keine Threads in Warteposition befinden, bleibt der signalisierte Zustand auf unbestimmte Zeit erhalten.
Sie können den Anfangszustand eines AutoResetEvent steuern, indem Sie dem Konstruktor einen booleschen Wert übergeben; true, wenn der Anfangszustand signalisiert ist, andernfalls false.
AutoResetEvent kann auch mit der staticWaitAll-Methode und der WaitAny-Methode verwendet werden.
Weitere Informationen zu Mechanismen zur Threadsynchronisierung finden Sie unter AutoResetEvent in der Dokumentation.
Im folgenden Codebeispiel wird die Verwendung von WaitHandles veranschaulicht, um bei einer komplizierten Berechnung eines Zahlenwerts den Abschluss verschiedener Stufen zu signalisieren. Die Berechnung hat folgende Form: result = first term + second term + third term, wobei für jeden Ausdruck eine Vorberechnung und eine Endberechnung mithilfe einer berechneten Basiszahl erforderlich ist.
using System; using System.Threading; class CalculateTest { static void Main() { Calculate calc = new Calculate(); Console.WriteLine("Result = {0}.", calc.Result(234).ToString()); Console.WriteLine("Result = {0}.", calc.Result(55).ToString()); } } class Calculate { double baseNumber, firstTerm, secondTerm, thirdTerm; AutoResetEvent[] autoEvents; ManualResetEvent manualEvent; // Generate random numbers to simulate the actual calculations. Random randomGenerator; public Calculate() { autoEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false), new AutoResetEvent(false) }; manualEvent = new ManualResetEvent(false); } void CalculateBase(object stateInfo) { baseNumber = randomGenerator.NextDouble(); // Signal that baseNumber is ready. manualEvent.Set(); } // The following CalculateX methods all perform the same // series of steps as commented in CalculateFirstTerm. void CalculateFirstTerm(object stateInfo) { // Perform a precalculation. double preCalc = randomGenerator.NextDouble(); // Wait for baseNumber to be calculated. manualEvent.WaitOne(); // Calculate the first term from preCalc and baseNumber. firstTerm = preCalc * baseNumber * randomGenerator.NextDouble(); // Signal that the calculation is finished. autoEvents[0].Set(); } void CalculateSecondTerm(object stateInfo) { double preCalc = randomGenerator.NextDouble(); manualEvent.WaitOne(); secondTerm = preCalc * baseNumber * randomGenerator.NextDouble(); autoEvents[1].Set(); } void CalculateThirdTerm(object stateInfo) { double preCalc = randomGenerator.NextDouble(); manualEvent.WaitOne(); thirdTerm = preCalc * baseNumber * randomGenerator.NextDouble(); autoEvents[2].Set(); } public double Result(int seed) { randomGenerator = new Random(seed); // Simultaneously calculate the terms. ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateBase)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateFirstTerm)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateSecondTerm)); ThreadPool.QueueUserWorkItem( new WaitCallback(CalculateThirdTerm)); // Wait for all of the terms to be calculated. WaitHandle.WaitAll(autoEvents); // Reset the wait handle for the next calculation. manualEvent.Reset(); return firstTerm + secondTerm + thirdTerm; } }
import System.*;
import System.Threading.*;
class CalculateTest
{
public static void main(String[] args)
{
Calculate calc = new Calculate();
Console.WriteLine("Result = {0}.", String.valueOf(calc.Result(234)));
Console.WriteLine("Result = {0}.", String.valueOf(calc.Result(55)));
} //main
} //CalculateTest
class Calculate
{
private double baseNumber, firstTerm, secondTerm, thirdTerm;
private AutoResetEvent autoEvents[];
private ManualResetEvent manualEvent;
// Generate random numbers to simulate the actual calculations.
private Random randomGenerator;
public Calculate()
{
autoEvents = new AutoResetEvent[] { new AutoResetEvent(false),
new AutoResetEvent(false), new AutoResetEvent(false) };
manualEvent = new ManualResetEvent(false);
} //Calculate
void CalculateBase(Object stateInfo)
{
baseNumber = randomGenerator.NextDouble();
// Signal that baseNumber is ready.
manualEvent.Set();
} //CalculateBase
// The following CalculateX methods all perform the same
// series of steps as commented in CalculateFirstTerm.
void CalculateFirstTerm(Object stateInfo)
{
// Perform a precalculation.
double preCalc = randomGenerator.NextDouble();
// Wait for baseNumber to be calculated.
manualEvent.WaitOne();
// Calculate the first term from preCalc and baseNumber.
firstTerm = preCalc * baseNumber * randomGenerator.NextDouble();
// Signal that the calculation is finished.
autoEvents[0].Set();
} //CalculateFirstTerm
void CalculateSecondTerm(Object stateInfo)
{
double preCalc = randomGenerator.NextDouble();
manualEvent.WaitOne();
secondTerm = preCalc * baseNumber * randomGenerator.NextDouble();
autoEvents[1].Set();
} //CalculateSecondTerm
void CalculateThirdTerm(Object stateInfo)
{
double preCalc = randomGenerator.NextDouble();
manualEvent.WaitOne();
thirdTerm = preCalc * baseNumber * randomGenerator.NextDouble();
autoEvents[2].Set();
} //CalculateThirdTerm
public double Result(int seed)
{
randomGenerator = new Random(seed);
// Simultaneously calculate the terms.
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateBase));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateFirstTerm));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateSecondTerm));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateThirdTerm));
// Wait for all of the terms to be calculated.
WaitHandle.WaitAll(autoEvents);
// Reset the wait handle for the next calculation.
manualEvent.Reset();
return firstTerm + secondTerm + thirdTerm;
} //Result
} //Calculate
System.MarshalByRefObject
System.Threading.WaitHandle
System.Threading.EventWaitHandle
System.Threading.AutoResetEvent
Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile für Pocket PC, Windows Mobile für Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
.NET Framework unterstützt nicht alle Versionen sämtlicher Plattformen. Eine Liste der unterstützten Versionen finden Sie unter Systemanforderungen.
Referenz
AutoResetEvent-MemberSystem.Threading-Namespace
WaitHandle
Weitere Ressourcen
Verwaltetes ThreadingAutoResetEvent
Hinweis