Notifica a uno o più thread in attesa che si è verificato un evento. La classe non può essere ereditata.
Spazio dei nomi: System.Threading
Assembly: mscorlib (in mscorlib.dll)
Visual Basic - (Dichiarazione)
<ComVisibleAttribute(True)> _
Public NotInheritable Class ManualResetEvent
Inherits EventWaitHandle
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
In .NET Framework versione 2.0, la classe ManualResetEvent deriva dalla nuova classe EventWaitHandle. Dal punto di vista funzionale, una classe ManualResetEvent è equivalente a una classe EventWaitHandle creata con EventResetMode.ManualReset.
Nota |
|---|
| A differenza della classe ManualResetEvent, la classe EventWaitHandle fornisce accesso agli eventi di sincronizzazione di sistema denominati. |
L'oggetto ManualResetEvent consente ai thread di comunicare tra loro tramite segnalazioni. Di solito questa comunicazione riguarda un'attività che deve essere completata da un thread perché gli altri thread possano procedere.
Quando un thread avvia un'attività che deve essere completata prima che gli altri thread possano procedere, viene chiamato il metodo Reset per impostare lo stato dell'evento ManualResetEvent su non segnalato. Lo si può considerare come un thread di controllo di ManualResetEvent. I thread che chiamano il metodo WaitOne nell'evento ManualResetEvent si interromperanno in attesa del segnale. Quando il thread di controllo completa l'attività, chiama il metodo Set per segnalare che i thread in attesa possono procedere . Tutti i thread in attesa vengono rilasciati.
Dopo essere stato segnalato, lo stato dell'evento ManualResetEvent rimane segnalato fino a quando non viene reimpostato manualmente. Ovvero, le chiamate a WaitOne vengono immediatamente restituite.
È possibile controllare lo stato iniziale dell'evento ManualResetEvent passando un valore booleano al costruttore: true se lo stato iniziale viene segnalato, in caso contrario false.
ManualResetEvent può inoltre essere utilizzato con i metodi staticWaitAll e WaitAny.
Per ulteriori informazioni sui meccanismi di sincronizzazione dei thread, vedere ManualResetEvent nella documentazione concettuale.
Nell'esempio di codice riportato di seguito viene illustrato come utilizzare gli handle di attesa per segnalare il completamento di varie fasi di un calcolo numerico complesso. Il calcolo presenta il formato: result = first term + second term + third term, dove ogni termine richiede un precalcolo e un calcolo finale utilizzando un numero base calcolato.
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
Gerarchia di ereditarietà
System.Object
System.MarshalByRefObject
System.Threading.WaitHandle
System.Threading.EventWaitHandle
System.Threading.ManualResetEvent
Questa classe è thread-safe.
Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile per Pocket PC, Windows Mobile per Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
.NET Framework non supporta tutte le versioni di ciascuna piattaforma. Per un elenco delle versioni supportate, vedere Requisiti di sistema.
Informazioni sulla versione
.NET Framework
Supportato in: 2.0 1.1 1.0
.NET Compact Framework
Supportato in: 2.0 1.0