다음을 통해 공유


CEvent 수업

한 스레드가 이벤트가 발생했음을 다른 스레드에 알릴 수 있도록 하는 동기화 개체인 이벤트를 나타냅니다.

구문

class CEvent : public CSyncObject

멤버

공용 생성자

속성 설명
CEvent::CEvent CEvent 개체를 생성합니다.

공용 메서드

이름 설명
CEvent::PulseEvent 이벤트를 사용 가능(신호)으로 설정하고, 대기 중인 스레드를 해제하고, 이벤트를 사용할 수 없도록 설정합니다(서명되지 않은).
CEvent::ResetEvent 이벤트를 사용할 수 없도록 설정합니다(부호 없음).
CEvent::SetEvent 이벤트를 사용 가능(신호)으로 설정하고 대기 중인 스레드를 해제합니다.
CEvent::Unlock 이벤트 개체를 해제합니다.

설명

이벤트는 스레드가 작업을 수행할 시기를 알아야 하는 경우에 유용합니다. 예를 들어 데이터를 데이터 보관에 복사하는 스레드는 새 데이터를 사용할 수 있을 때 알림을 받아야 합니다. 새 데이터를 사용할 수 있을 때 개체를 사용하여 CEvent 복사 스레드에 알리면 스레드는 가능한 한 빨리 해당 작업을 수행할 수 있습니다.

CEvent 개체에는 수동 및 자동의 두 가지 유형이 있습니다.

하나 이상의 스레드가 해제된 후 자동 CEvent 개체는 신호가 없는(사용할 수 없음) 상태로 자동으로 돌아갑니다. 기본적으로 CEvent 생성 중에 매개 변수를 전달 TRUE 하지 않으면 개체가 bManualReset 자동으로 설정됩니다.

수동 CEvent 개체는 다른 함수에 의해 SetEvent 또는 ResetEvent 다른 함수가 호출될 때까지 설정된 상태로 유지됩니다. 수동 CEvent 개체를 만들려면 생성 중에 매개 변수를 bManualReset 전달 TRUE 합니다.

개체를 CEvent 사용하려면 필요한 경우 개체를 CEvent 생성합니다. 대기할 이벤트의 이름을 지정하고 애플리케이션이 처음에 이벤트를 소유하도록 지정합니다. 그런 다음 생성자가 반환되면 이벤트에 액세스할 수 있습니다. 이벤트 개체의 신호를 호출 SetEvent (사용 가능)한 다음 제어된 리소스에 대한 액세스가 완료되면 호출 Unlock 합니다.

개체를 사용하는 CEvent 다른 방법은 제어하려는 클래스에 형식 CEvent 변수를 데이터 멤버로 추가하는 것입니다. 제어된 개체를 생성하는 동안 데이터 멤버의 CEvent 생성자를 호출하고 이벤트가 처음에 신호를 받을지 여부를 지정하고, 원하는 이벤트 개체의 형식, 이벤트 이름(프로세스 경계를 넘어 사용될 경우) 및 원하는 보안 특성을 지정합니다.

이러한 방식으로 개체에 의해 제어되는 리소스에 CEvent 액세스하려면 먼저 리소스의 액세스 메서드에서 형식 CSingleLock 또는 형식 CMultiLock 의 변수를 만듭니다. 그런 다음 개체의 Lock lock 메서드(예: CMultiLock::Lock)를 호출합니다. 이 시점에서 스레드는 리소스에 대한 액세스 권한을 얻거나, 리소스가 해제될 때까지 기다리거나, 액세스 권한을 얻거나, 리소스가 해제될 때까지 기다리거나, 시간이 초과되고, 리소스에 대한 액세스 권한을 얻지 못합니다. 어떤 경우든 리소스가 스레드로부터 안전한 방식으로 액세스되었습니다. 리소스를 해제하려면 이벤트 개체의 신호를 호출 SetEvent 한 다음 개체의 lock 메서드(예: CMultiLock::Unlock)를 사용 Unlock 하거나 개체가 lock 범위를 벗어나게 합니다.

개체를 사용하는 CEvent 방법에 대한 자세한 내용은 다중 스레딩: 동기화 클래스를 사용하는 방법을 참조하세요.

예시

// The following demonstrates trivial usage of the CEvent class.
// A CEvent object is created and passed as a parameter to another
// thread.  The other thread will wait for the event to be signaled
// and then exit

UINT __cdecl MyThreadProc(LPVOID lpParameter)
{
   CEvent *pEvent = (CEvent *)(lpParameter);
   VERIFY(pEvent != NULL);

   // Wait for the event to be signaled
   ::WaitForSingleObject(pEvent->m_hObject, INFINITE);

   // Terminate the thread
   ::AfxEndThread(0, FALSE);
   return 0L;
}

void CEvent_Test()
{
   // Create the CEvent object that will be passed to the thread routine
   CEvent *pEvent = new CEvent(FALSE, FALSE);

   // Create a thread that will wait on the event
   CWinThread *pThread;
   pThread = ::AfxBeginThread(&MyThreadProc, pEvent, 0, 0, CREATE_SUSPENDED, NULL);
   pThread->m_bAutoDelete = FALSE;
   pThread->ResumeThread();

   // Signal the thread to do the next work item
   pEvent->SetEvent();

   // Wait for the thread to consume the event and return
   ::WaitForSingleObject(pThread->m_hThread, INFINITE);
   delete pThread;
   delete pEvent;
}

 

// This example builds upon the previous one.
// A second thread is created to calculate prime numbers.
// The main thread will signal the second thread to calculate the next
// prime number in the series.  The second thread signals the first
// after each number is calculated. Finally, after several iterations
// the worker thread is signaled to terminate.

class CPrimeTest
{
public:
   CPrimeTest()
       : m_pCalcNext(new CEvent(FALSE, FALSE)),
         m_pCalcFinished(new CEvent(FALSE, FALSE)),
         m_pTerminateThread(new CEvent(FALSE, FALSE)),
         m_iCurrentPrime(0)
   {
      // Create a thread that will calculate the prime numbers
      CWinThread *pThread;
      pThread = ::AfxBeginThread(&PrimeCalcProc,
                                 this, 0, 0, CREATE_SUSPENDED, NULL);
      pThread->m_bAutoDelete = FALSE;
      pThread->ResumeThread();

      // Calcuate the first 10 prime numbers in the series on the thread
      for (UINT i = 0; i < 10; i++)
      {
         // Signal the thread to do the next work item
         m_pCalcNext->SetEvent();
         // Wait for the thread to complete the current task
         ::WaitForSingleObject(m_pCalcFinished->m_hObject, INFINITE);
         // Print the result
         TRACE(_T("The value of m_iCurrentPrime is: %d\n"), m_iCurrentPrime);
      }

      // Notify the worker thread to exit and wait for it to complete
      m_pTerminateThread->SetEvent();
      ::WaitForSingleObject(pThread->m_hThread, INFINITE);
      delete pThread;
   }
   ~CPrimeTest()
   {
      delete m_pCalcNext;
      delete m_pCalcFinished;
      delete m_pTerminateThread;
   }

private:
   // Determines whether the given number is a prime number
   static BOOL IsPrime(INT ThisPrime)
   {
      if (ThisPrime < 2)
         return FALSE;

      for (INT n = 2; n < ThisPrime; n++)
      {
         if (ThisPrime % n == 0)
            return FALSE;
      }
      return TRUE;
   }

   // Calculates the next prime number in the series
   static INT NextPrime(INT ThisPrime)
   {
      while (TRUE)
      {
         if (IsPrime(++ThisPrime))
         {
            return ThisPrime;
         }
      }
   }

   // Worker thread responsible for calculating the next prime
   // number in the series
   static UINT __cdecl PrimeCalcProc(LPVOID lpParameter)
   {
      CPrimeTest *pThis = static_cast<CPrimeTest *>(lpParameter);
      VERIFY(pThis != NULL);

      VERIFY(pThis->m_pCalcNext != NULL);
      VERIFY(pThis->m_pCalcFinished != NULL);
      VERIFY(pThis->m_pTerminateThread != NULL);

      // Create a CMultiLock object to wait on the various events
      // WAIT_OBJECT_0 refers to the first event in the array,
      // WAIT_OBJECT_0+1 refers to the second
      CSyncObject *pWaitObjects[] = {pThis->m_pCalcNext,
                                     pThis->m_pTerminateThread};
      CMultiLock MultiLock(pWaitObjects, 2L);
      while (MultiLock.Lock(INFINITE, FALSE) == WAIT_OBJECT_0)
      {
         // Calculate next prime
         pThis->m_iCurrentPrime = NextPrime(pThis->m_iCurrentPrime);
         // Notify main thread calculation is complete
         pThis->m_pCalcFinished->SetEvent();
      }

      // Terminate the thread
      ::AfxEndThread(0, FALSE);
      return 0L;
   }

   CEvent *m_pCalcNext;        // notifies worker thread to calculate next prime
   CEvent *m_pCalcFinished;    // notifies main thread current calculation is complete
   CEvent *m_pTerminateThread; // notifies worker thread to terminate

   INT m_iCurrentPrime; // current calculated prime number
};

상속 계층 구조

CObject

CSyncObject

CEvent

요구 사항

머리글: afxmt.h

CEvent::CEvent

명명되거나 명명되지 않은 개체를 CEvent 생성합니다.

CEvent(
    BOOL bInitiallyOwn = FALSE,
    BOOL bManualReset = FALSE,
    LPCTSTR lpszName = NULL,
    LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);

매개 변수

bInitiallyOwn
이 경우 TRUE또는 CSingleLock 개체에 대한 스레드를 CMultilock 사용할 수 있습니다. 그렇지 않으면 리소스에 액세스하려는 모든 스레드가 기다려야 합니다.

bManualReset
이벤트 개체가 수동 이벤트임을 지정하면 TRUE이벤트 개체가 자동 이벤트입니다.

lpszName
CEvent 개체의 이름입니다. 개체가 프로세스 경계를 넘어 사용되는 경우 제공해야 합니다. 이름이 기존 이벤트와 일치하는 경우 생성자는 해당 이름의 이벤트를 참조하는 새 CEvent 개체를 빌드합니다. 이름이 이벤트가 아닌 기존 동기화 개체와 일치하면 생성에 실패합니다. 이 경우 NULL이름은 null이 됩니다.

lpsaAttribute
이벤트 개체의 보안 특성입니다. 이 구조에 대한 전체 설명은 Windows SDK를 참조 SECURITY_ATTRIBUTES 하세요.

설명

개체에 CEvent 액세스하거나 해제하려면 개체를 CMultiLock CSingleLock 만들고 해당 Lock 함수와 Unlock 멤버 함수를 호출합니다.

개체의 CEvent 상태를 신호로 변경하려면(스레드가 대기할 필요가 없습니다), 호출 SetEvent 또는 PulseEvent. 개체의 CEvent 상태를 부호 없는 상태로 설정하려면(스레드는 대기해야 합니다) 호출 ResetEvent합니다.

Important

개체를 CEvent 만든 후 뮤텍스가 아직 없는지 확인하는 데 사용합니다 GetLastError . 뮤텍스가 예기치 않게 존재했다면 불량 프로세스가 웅크리고 있음을 나타낼 수 있으며 뮤텍스를 악의적으로 사용하려고 할 수 있습니다. 이 경우 권장되는 보안 의식 프로시저는 핸들을 닫고 개체를 만드는 데 오류가 있는 것처럼 계속 진행하는 것입니다.

CEvent::PulseEvent

이벤트의 상태를 신호(사용 가능)로 설정하고, 대기 중인 스레드를 해제하고, 자동으로 서명되지 않은(사용할 수 없음)으로 다시 설정합니다.

BOOL PulseEvent();

Return Value

함수가 성공한 경우 0이 아닌 경우 그렇지 않으면 0입니다.

설명

이벤트가 수동인 경우 대기 중인 모든 스레드가 해제되고 이벤트가 서명되지 않은 것으로 설정되고 PulseEvent 반환됩니다. 이벤트가 자동이면 단일 스레드가 해제되고, 이벤트가 부호 없는 것으로 설정되고 PulseEvent , 반환됩니다.

대기 중인 스레드가 없거나 스레드를 즉시 PulseEvent 해제할 수 없는 경우 이벤트의 상태를 부호 없는 상태로 설정하고 반환합니다.

PulseEvent 에서는 커널 모드 비동기 프로시저 호출을 통해 대기 상태에서 잠시 제거할 수 있는 기본 Win32 PulseEvent 함수를 사용합니다. 따라서 PulseEvent 신뢰할 수 없으며 새 애플리케이션에서 사용하면 안 됩니다. 자세한 정보는 PulseEvent 함수를 참조하세요.

CEvent::ResetEvent

멤버 함수에서 명시적으로 신호를 SetEvent 보낼 때까지 이벤트의 상태를 서명되지 않은 상태로 설정합니다.

BOOL ResetEvent();

Return Value

함수가 성공한 경우 0이 아닌 경우 그렇지 않으면 0입니다.

설명

이렇게 하면 이 이벤트에 액세스하려는 모든 스레드가 대기합니다.

이 멤버 함수는 자동 이벤트에서 사용되지 않습니다.

CEvent::SetEvent

이벤트 상태를 신호로 설정하여 대기 중인 스레드를 해제합니다.

BOOL SetEvent();

Return Value

함수가 성공하면 0이 아니고, 그렇지 않으면 0입니다.

설명

이벤트가 수동인 경우 이벤트가 호출될 때까지 ResetEvent 신호로 유지됩니다. 이 경우 둘 이상의 스레드를 해제할 수 있습니다. 이벤트가 자동인 경우 단일 스레드가 해제될 때까지 이벤트가 신호를 계속 표시합니다. 그런 다음 시스템은 이벤트의 상태를 서명되지 않은 상태로 설정합니다. 대기 중인 스레드가 없으면 한 스레드가 해제될 때까지 상태가 신호로 유지됩니다.

CEvent::Unlock

이벤트 개체를 해제합니다.

BOOL Unlock();

Return Value

스레드가 이벤트 개체를 소유하고 이벤트가 자동 이벤트인 경우 0이 아닌 경우 그렇지 않으면 0입니다.

설명

이 멤버 함수는 현재 자동 이벤트를 소유하고 있는 스레드에서 호출되어 개체를 다시 사용할 경우 lock 완료된 후 해제합니다. 개체를 lock 다시 사용하지 않을 경우 개체의 소멸자가 이 함수를 lock 호출합니다.

참고 항목

CSyncObject 클래스
계층 구조 차트