このドキュメントはアーカイブされており、メンテナンスされていません。

AutoResetEvent クラス

更新 : 2007 年 11 月

イベントが発生したことを待機中のスレッドに通知します。このクラスは継承できません。

名前空間 :  System.Threading
アセンブリ :  mscorlib (mscorlib.dll 内)

[ComVisibleAttribute(true)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
	ExternalThreading = true)]
public sealed class AutoResetEvent : EventWaitHandle
/** @attribute ComVisibleAttribute(true) */
/** @attribute HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true) */
public final class AutoResetEvent extends EventWaitHandle
public final class AutoResetEvent extends EventWaitHandle

メモ :

この型またはメンバに適用される HostProtectionAttribute 属性の Resources プロパティの値は、Synchronization | ExternalThreading です。HostProtectionAttribute は、デスクトップ アプリケーション (通常、アイコンのダブルクリック、コマンドの入力、またはブラウザへの URL の入力により起動されます) には影響しません。詳細については、HostProtectionAttribute クラスのトピックまたは「SQL Server プログラミングとホスト保護属性」を参照してください。

.NET Framework Version 2.0 では、AutoResetEvent は新しい EventWaitHandle クラスから派生します。AutoResetEvent は、機能的には EventResetMode.AutoReset で作成した EventWaitHandle と同等です。

メモ :

AutoResetEvent クラスとは異なり、EventWaitHandle クラスは名前付きシステム同期イベントへのアクセスを提供します。

AutoResetEvent を使用すると、スレッドはシグナルを通じて相互に通信できます。通常、このような通信は、複数のスレッドが 1 つのリソースに対して排他的なアクセスを必要とする場合に使用します。

スレッドは AutoResetEventWaitOne を呼び出すことによってシグナルを待機します。AutoResetEvent が非シグナル状態の場合、スレッドはブロックし、リソースを現在制御しているスレッドが Set を呼び出すことによってリソースが使用可能になったことをシグナル通知するまで待機します。

Set を呼び出すと、AutoResetEvent にシグナルが送られ、待機しているスレッドが解放されます。AutoResetEvent は、待機しているスレッドが解放されるまでシグナル状態のままとなり、最後のスレッドが解放されると自動的に非シグナル状態に戻ります。待機中のスレッドがない場合、状態は無限にシグナル状態のままです。

AutoResetEvent がシグナル状態にある間にスレッドが WaitOne を呼び出す場合、スレッドはブロックしません。AutoResetEvent はそのスレッドを即時に解放し、非シグナル状態に戻ります。

重要 :

Set メソッドのすべての呼び出しでスレッドが解放されるという保証はありません。2 回の呼び出しの間隔が近すぎて、スレッドが解放される前に 2 回目の呼び出しが行われた場合、1 つのスレッドしか解放されません。この場合、2 回目の呼び出しが行われなかったかのような結果となります。また、待機中のスレッドが存在せず、AutoResetEvent が既にシグナル状態のときに Set が呼び出された場合、その呼び出しは無効です。

AutoResetEvent の初期状態は、コンストラクタに Boolean 値を渡すことによって制御できます。初期状態をシグナル状態にする場合は true を渡し、それ以外の場合は false を渡します。

AutoResetEvent は、staticWaitAll メソッドおよび WaitAny メソッドでも使用できます。

スレッドの同期機構の詳細については、概念説明のドキュメントの「AutoResetEvent」を参照してください。

待機ハンドルを使用して、複雑な数値計算の各段階の完了をシグナル通知する例を次に示します。計算の形式は、result = first term + second term + third term です。各項目には、事前計算と、算出された基数を使用した最終計算が行われます。

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;
    }
}


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


このクラスは、スレッド セーフです。

Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC, Xbox 360

.NET Framework および .NET Compact Framework では、各プラットフォームのすべてのバージョンはサポートしていません。サポートされているバージョンについては、「.NET Framework システム要件」を参照してください。

.NET Framework

サポート対象 : 3.5、3.0、2.0、1.1、1.0

.NET Compact Framework

サポート対象 : 3.5、2.0、1.0

XNA Framework

サポート対象 : 2.0、1.0
表示: