CEvent Class
表示一个事件,是同步对象允许一个线程通知另一个操作的。
class CEvent : public CSyncObject
成员
公共构造函数
名称 |
说明 |
---|---|
构造 CEvent 对象。 |
公共方法
名称 |
说明 |
---|---|
将等待线程的活动为可用(终止),版本,并将事件设置可用(nonsignaled)。 |
|
将事件设置可用(nonsignaled)。 |
|
将事件设置可用(终止)和版本所有等待线程。 |
|
释放事件对象。 |
备注
当线程时必须知道执行其任务时,事件非常有用。 例如,复制的线程传递数据的数据存档必须注意,在新数据可用时。 通过使用通知该副本的 CEvent 对象的线程,在新数据可用,线程可以尽快执行其任务。
CEvent 对象有两种类型:手动和自动。
一个自 CEvent 对象自动恢复为非终止(可用)状态,在释放后至少有一个线程。 默认情况下,除非在构造期间,通过 bManualReset 参数的 TRUECEvent 对象是自动的。
准则 CEvent 对象在 SetEvent 或 ResetEvent 设置的状态保持,直到另一个函数调用。 若要创建手动 CEvent 对象,请在构造时传递 bManualReset 参数的 TRUE。
在需要时,要使用 CEvent 对象,请构造 CEvent 对象。 指定要等待事件的名称,并指定应用程序最初应拥有它。 当构造函数返回时,您可以访问该事件。 调用 SetEvent 发出信号(可用时)事件对象并调用 unlock,在执行这种访问受控资源后。
另一种方法用于 CEvent 对象将添加 CEvent 类型的变量,要控件的选件类的数据成员。 在控制构造对象时,只需调用 CEvent 数据成员的构造函数并指定事件最初是否收到信号,然后的事件对象的specifythe类型需要,事件的名称(如果它将用作进程边界)和所需的任何安全特性。
访问 CEvent 对象来控件的资源,首先创建类型 CSingleLock 的变量或键入在资源访问方法的 CMultiLock。 然后调用锁定对象(例如,CMultiLock::Lock)的 Lock 方法。 此时,您的线程对该资源将能够访问,等待资源释放并且能够访问或等待资源释放,时间和未对该资源的访问权。 在任一情况下,您的资源访问了采用线程安全的方式。 若要释放资源,调用 SetEvent 用于通知事件对象,然后使用锁定对象的 Unlock 方法(例如,CMultiLock::Unlock),或者允许锁定对象由超出范围。
有关如何使用 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 calulate 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
要求
Header: afxmt.h