次の方法で共有


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 を制御していると見なすことができます。 ManualResetEventWaitOne を呼び出したスレッドは、ブロックしてシグナルを待機します。制御しているスレッドは処理を完了したら、 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