ManualResetEvent-Klasse
Benachrichtigt einen oder mehrere wartende Threads über das Eintreten eines Ereignisses. Diese Klasse kann nicht vererbt werden.
Namespace: System.Threading
Assembly: mscorlib (in mscorlib.dll)
Syntax
'Declaration
<ComVisibleAttribute(True)> _
Public NotInheritable Class ManualResetEvent
Inherits EventWaitHandle
'Usage
Dim instance As ManualResetEvent
[ComVisibleAttribute(true)]
public sealed class ManualResetEvent : EventWaitHandle
[ComVisibleAttribute(true)]
public ref class ManualResetEvent sealed : public EventWaitHandle
/** @attribute ComVisibleAttribute(true) */
public final class ManualResetEvent extends EventWaitHandle
ComVisibleAttribute(true)
public final class ManualResetEvent extends EventWaitHandle
Hinweise
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 ManualResetEvent von der neuen EventWaitHandle-Klasse abgeleitet. Eine ManualResetEvent-Klasse ist hinsichtlich ihrer Funktion gleichwertig mit einer EventWaitHandle-Klasse, die mit dem EventResetMode.ManualReset-Flag erstellt wird.
Hinweis
Anders als die ManualResetEvent-Klasse ermöglicht die EventWaitHandle-Klasse den Zugriff auf benannte Systemsynchronisierungsereignisse.
Mit ManualResetEvent können Threads untereinander durch Signalisieren kommunizieren. Diese Kommunikation betrifft in erster Linie Tasks, die von einem Thread beendet werden müssen, bevor ein anderer Thread fortfahren kann.
Wenn ein Thread eine Aktivität beginnt, die vor dem Fortfahren anderer Threads beendet sein muss, wird die Reset-Methode aufgerufen, um für ManualResetEvent den nicht signalisierten Zustand festzulegen. Dieser Thread steuert gewissermaßen das ManualResetEvent. Threads, die WaitOne für ManualResetEvent aufrufen, werden blockiert und warten auf das Signal. Wenn der steuernde Thread die Aktivität beendet, wird Set aufgerufen und damit signalisiert, dass die wartenden Threads fortfahren können. Alle wartenden Threads werden freigegeben.
Nachdem der signalisierte Zustand einmal festgelegt wurde, bleibt ManualResetEvent bis zum manuellen Zurücksetzen im signalisierten Zustand. Aufrufe von WaitOne werden also sofort zurückgegeben.
Sie können den Anfangszustand eines ManualResetEvent steuern, indem Sie dem Konstruktor einen booleschen Wert übergeben; true, wenn der Anfangszustand signalisiert ist, andernfalls false.
ManualResetEvent kann auch mit der staticWaitAll-Methode und der WaitAny-Methode verwendet werden.
Weitere Informationen über Verfahren für die Threadsynchronisierung finden Sie in der Dokumentation unter ManualResetEvent.
Beispiel
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.
Imports System
Imports System.Threading
Public Class CalculateTest
<MTAThreadAttribute> _
Shared Sub Main()
Dim calc As New Calculate()
Console.WriteLine("Result = {0}.", _
calc.Result(234).ToString())
Console.WriteLine("Result = {0}.", _
calc.Result(55).ToString())
End Sub
End Class
Public Class Calculate
Dim baseNumber, firstTerm, secondTerm, thirdTerm As Double
Dim autoEvents() As AutoResetEvent
Dim manualEvent As ManualResetEvent
' Generate random numbers to simulate the actual calculations.
Dim randomGenerator As Random
Sub New()
autoEvents = New AutoResetEvent(2) { _
New AutoResetEvent(False), _
New AutoResetEvent(False), _
New AutoResetEvent(False) }
manualEvent = New ManualResetEvent(False)
End Sub
Private Sub CalculateBase(stateInfo As Object)
baseNumber = randomGenerator.NextDouble()
' Signal that baseNumber is ready.
manualEvent.Set()
End Sub
' The following CalculateX methods all perform the same
' series of steps as commented in CalculateFirstTerm.
Private Sub CalculateFirstTerm(stateInfo As Object)
' Perform a precalculation.
Dim preCalc As Double = 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()
End Sub
Private Sub CalculateSecondTerm(stateInfo As Object)
Dim preCalc As Double = randomGenerator.NextDouble()
manualEvent.WaitOne()
secondTerm = preCalc * baseNumber * _
randomGenerator.NextDouble()
autoEvents(1).Set()
End Sub
Private Sub CalculateThirdTerm(stateInfo As Object)
Dim preCalc As Double = randomGenerator.NextDouble()
manualEvent.WaitOne()
thirdTerm = preCalc * baseNumber * _
randomGenerator.NextDouble()
autoEvents(2).Set()
End Sub
Function Result(seed As Integer) As Double
randomGenerator = New Random(seed)
' Simultaneously calculate the terms.
ThreadPool.QueueUserWorkItem(AddressOf CalculateBase)
ThreadPool.QueueUserWorkItem(AddressOf CalculateFirstTerm)
ThreadPool.QueueUserWorkItem(AddressOf CalculateSecondTerm)
ThreadPool.QueueUserWorkItem(AddressOf 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
End Function
End Class
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;
}
}
using namespace System;
using namespace System::Threading;
ref class Calculate
{
private:
double baseNumber;
double firstTerm;
double secondTerm;
double thirdTerm;
array<AutoResetEvent^>^autoEvents;
ManualResetEvent^ manualEvent;
// Generate random numbers to simulate the actual calculations.
Random^ randomGenerator;
public:
Calculate()
{
autoEvents = gcnew array<AutoResetEvent^>(3);
autoEvents[ 0 ] = gcnew AutoResetEvent( false );
autoEvents[ 1 ] = gcnew AutoResetEvent( false );
autoEvents[ 2 ] = gcnew AutoResetEvent( false );
manualEvent = gcnew ManualResetEvent( false );
}
private:
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 = gcnew Random( seed );
// Simultaneously calculate the terms.
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Calculate::CalculateBase ) );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Calculate::CalculateFirstTerm ) );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Calculate::CalculateSecondTerm ) );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Calculate::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;
}
};
int main()
{
Calculate^ calc = gcnew Calculate;
Console::WriteLine( "Result = {0}.", calc->Result( 234 ).ToString() );
Console::WriteLine( "Result = {0}.", calc->Result( 55 ).ToString() );
}
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
Vererbungshierarchie
System.Object
System.MarshalByRefObject
System.Threading.WaitHandle
System.Threading.EventWaitHandle
System.Threading.ManualResetEvent
Threadsicherheit
Diese Klasse ist threadsicher.
Plattformen
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.
Versionsinformationen
.NET Framework
Unterstützt in: 2.0, 1.1, 1.0
.NET Compact Framework
Unterstützt in: 2.0, 1.0
Siehe auch
Referenz
ManualResetEvent-Member
System.Threading-Namespace
WaitHandle