ManualResetEvent クラス
イベントが発生したことを、1 つ以上の待機中のスレッドに通知します。このクラスは継承できません。
この型のすべてのメンバの一覧については、ManualResetEvent メンバ を参照してください。
System.Object
System.MarshalByRefObject
System.Threading.WaitHandle
System.Threading.ManualResetEvent
NotInheritable Public Class ManualResetEvent
Inherits WaitHandle
[C#]
public sealed class ManualResetEvent : WaitHandle
[C++]
public __gc __sealed class ManualResetEvent : public WaitHandle
[JScript]
public class ManualResetEvent extends WaitHandle
スレッドセーフ
この型は、マルチスレッド操作に対して安全です。
解説
ManualResetEvent を使用すると、スレッドはシグナルを通じて相互に通信できます。一般的に、この通信は、あるスレッドが完了しないと別のスレッドが続行できない処理で必要となります。
完了しないと他のスレッドが続行できない処理を開始するスレッドは、 Reset を呼び出して ManualResetEvent を非シグナル状態にします。このスレッドは、 ManualResetEvent を制御していると見なすことができます。 ManualResetEvent の WaitOne を呼び出したスレッドは、ブロックしてシグナルを待機します。制御しているスレッドは処理を完了したら、 Set を呼び出して、待機しているスレッドに対して続行できることを示すシグナルを送ります。待機しているスレッドはすべて解放されます。
シグナルを受け取ると、 ManualResetEvent は、手動でリセットされるまでシグナル状態になります。つまり、 WaitOne の呼び出しはすぐに終了します。
ManualResetEvent の初期状態は、コンストラクタに Boolean 値を渡すことによって制御できます。初期状態をシグナル状態にする場合は true を渡し、それ以外の場合は false を渡します。
ManualResetEvent は、静的な (Visual Basic では Shared の) WaitAll メソッドおよび WaitAny メソッドと組み合わせても使用できます。
スレッドの同期機構の詳細については、概念説明のドキュメントの「 ManualResetEvent 」を参照してください。
使用例
[Visual Basic, C#, C++] 待機ハンドルを使用して、複雑な数値計算の各段階の完了をシグナル通知する例を次に示します。計算の形式は、 result = first term + second
term + third term です。各項目には、事前計算と、算出された基数を使用した最終計算が行われます。
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
[C#]
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;
}
}
[C++]
#using <mscorlib.dll>
using namespace System;
using namespace System::Threading;
__gc class Calculate
{
double baseNumber, firstTerm, secondTerm, thirdTerm;
AutoResetEvent* autoEvents __gc [];
ManualResetEvent* manualEvent;
// Generate random numbers to simulate the actual calculations.
Random* randomGenerator;
public:
Calculate()
{
autoEvents = new AutoResetEvent* __gc [3];
autoEvents[0] = new AutoResetEvent(false);
autoEvents[1] = new AutoResetEvent(false);
autoEvents[2] = new AutoResetEvent(false);
manualEvent = new 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 = new Random(seed);
// Simultaneously calculate the terms.
ThreadPool::QueueUserWorkItem(
new WaitCallback(this, &Calculate::CalculateBase));
ThreadPool::QueueUserWorkItem(
new WaitCallback(this, &Calculate::CalculateFirstTerm));
ThreadPool::QueueUserWorkItem(
new WaitCallback(this, &Calculate::CalculateSecondTerm));
ThreadPool::QueueUserWorkItem(
new 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;
}
};
void main()
{
Calculate* calc = new Calculate();
Console::WriteLine(S"Result = {0}.",
calc->Result(234).ToString());
Console::WriteLine(S"Result = {0}.",
calc->Result(55).ToString());
}
[JScript] JScript のサンプルはありません。Visual Basic、C#、および C++ のサンプルを表示するには、このページの左上隅にある言語のフィルタ ボタン をクリックします。
必要条件
名前空間: System.Threading
プラットフォーム: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 ファミリ, .NET Compact Framework - Windows CE .NET
アセンブリ: Mscorlib (Mscorlib.dll 内)
参照
ManualResetEvent メンバ | System.Threading 名前空間 | スレッド処理 | ManualResetEvent