다음을 통해 공유


ManualResetEvent 클래스

하나 이상의 대기 중인 스레드에 이벤트가 발생했음을 알립니다. 이 클래스는 상속될 수 없습니다.

네임스페이스: System.Threading
어셈블리: mscorlib(mscorlib.dll)

구문

‘선언
<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

설명

참고

이 클래스에 적용되는 HostProtectionAttribute 특성의 Resources 속성 값은 Synchronization | ExternalThreading입니다. HostProtectionAttribute는 대개 아이콘을 두 번 클릭하거나, 명령을 입력하거나, 브라우저에서 URL을 입력하여 시작되는 데스크톱 응용 프로그램에 영향을 미치지 않습니다. 자세한 내용은 HostProtectionAttribute 클래스나 SQL Server 프로그래밍 및 호스트 보호 특성을 참조하십시오.

.NET Framework 버전 2.0에서는 ManualResetEvent가 새 EventWaitHandle 클래스에서 파생됩니다. ManualResetEventEventResetMode.ManualReset을 사용하여 만든 EventWaitHandle과 기능이 같습니다.

참고

ManualResetEvent 클래스와는 달리 EventWaitHandle 클래스는 명명된 시스템 동기화 이벤트에 대한 액세스를 제공합니다.

ManualResetEvent를 사용하여 스레드는 신호를 보냄으로써 서로 통신할 수 있습니다. 일반적으로 이 통신은 다른 스레드가 처리되기 위해 먼저 하나의 스레드가 완료해야 하는 작업과 관련이 있습니다.

하나의 스레드에서 다른 스레드의 처리를 위해 먼저 완료되어야 하는 작업을 시작할 때 Reset을 호출하여 ManualResetEvent를 신호 없음 상태로 설정합니다. 이 스레드는 ManualResetEvent를 제어하는 것으로 간주될 수 있습니다. ManualResetEvent에 대해 WaitOne을 호출하는 스레드는 차단되며 신호를 기다립니다. 제어 스레드는 해당 작업을 끝나면 Set을 호출하여 대기 중인 스레드가 계속될 수 있음을 알립니다. 대기 중인 모든 스레드는 해제됩니다.

일단 신호 받음 상태가 되면 ManualResetEvent는 수동으로 다시 설정될 때까지 신호 받음 상태로 남아 있습니다. 즉, WaitOne 호출이 즉시 반환됩니다.

초기 상태가 통보될 경우 부울 값 true를, 그렇지 않을 경우 false를 생성자에게 전달하여 ManualResetEvent의 초기 상태를 제어할 수 있습니다.

ManualResetEventstaticWaitAllWaitAny 메서드와 함께 사용할 수도 있습니다.

스레드 동기화 메커니즘에 대한 자세한 내용은 개념 설명서에서 ManualResetEvent를 참조하십시오.

예제

다음 코드 예제에서는 대기 핸들을 사용하여 복잡한 숫자 계산의 여러 단계에 대한 완료를 알리는 방법을 보여 줍니다. 계산은 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
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

상속 계층 구조

System.Object
   System.MarshalByRefObject
     System.Threading.WaitHandle
       System.Threading.EventWaitHandle
        System.Threading.ManualResetEvent

스레드로부터의 안전성

이 클래스는 스레드로부터 안전합니다.

플랫폼

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

.NET Framework에서 모든 플래폼의 모든 버전을 지원하지는 않습니다. 지원되는 버전의 목록은 시스템 요구 사항을 참조하십시오.

버전 정보

.NET Framework

2.0, 1.1, 1.0에서 지원

.NET Compact Framework

2.0, 1.0에서 지원

참고 항목

참조

ManualResetEvent 멤버
System.Threading 네임스페이스
WaitHandle

기타 리소스

관리되는 스레딩
ManualResetEvent