CEvent, terminate thread

本文详细介绍了CEvent类的使用方法及特点。CEvent类作为同步对象,用于线程间通信,支持手动和自动两种类型。文章通过实例展示了如何创建CEvent对象并利用其进行线程间的任务通知。
MFC Library Reference 
CEvent Class 

Represents an "event" — a synchronization object that allows one thread to notify another that an event has occurred.

class CEvent : public CSyncObject
RemarksRemarks

Events are useful when a thread needs to know when to perform its task. For example, a thread that copies data to a data archive would need to be notified when new data is available. By using a CEvent object to notify the copy thread when new data is available, the thread can perform its task as soon as possible.

CEvent objects have two types: manual and automatic. A manual CEvent object stays in the state set by SetEvent or ResetEvent until the other function is called. An automatic CEvent object automatically returns to a nonsignaled (unavailable) state after at least one thread is released.

To use a CEvent object, construct the CEvent object when it is needed. Specify the name of the event you wish to wait on, and that your application should initially own it. You can then access the event when the constructor returns. Call SetEvent to signal (make available) the event object and then call Unlock when you are done accessing the controlled resource.

An alternative method for using CEvent objects is to add a variable of type CEvent as a data member to the class you wish to control. During construction of the controlled object, call the constructor of the CEvent data member specifying if the event is initially signaled, the type of event object you want, the name of the event (if it will be used across process boundaries), and desired security attributes.

To access a resource controlled by a CEvent object in this manner, first create a variable of either type CSingleLock or type CMultiLock in your resource's access member function. Then call the lock object's Lock member function (for example, CMultiLock::Lock). At this point, your thread will either gain access to the resource, wait for the resource to be released and gain access, or wait for the resource to be released and time out, failing to gain access to the resource. In any case, your resource has been accessed in a thread-safe manner. To release the resource, call SetEvent to signal the event object, and then use the lock object's Unlock member function (for example, CMultiLock::Unlock), or allow the lock object to fall out of scope.

For more information on using CEvent objects, see the article Multithreading: How to Use the Synchronization Classes.

ExampleExample
// 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
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( ThreadProc, 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;
}
UINT __cdecl ThreadProc( 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;
}
// 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( "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
};

转载于:https://www.cnblogs.com/cy163/archive/2006/11/06/551658.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值