Freigeben über


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

Weitere Ressourcen

Verwaltetes Threading
ManualResetEvent