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
};
상속 계층 구조
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
호출합니다.