CEvent クラス
イベントを表します。これは、あるスレッドから別のスレッドにイベントの発生を通知できるようにする同期オブジェクトです。
class CEvent : public CSyncObject
メンバー
パブリック コンストラクター
名前 |
説明 |
---|---|
CEvent オブジェクトを構築します。 |
パブリック メソッド
名前 |
説明 |
---|---|
使用できる (シグナル状態)、リリースの待機中のスレッドおよび使用不可能にセットにイベントをイベント設定します (非シグナル状態)。 |
|
使用不可能に設定します (nonsignaled)。 |
|
使用できる (シグナル状態) とリリースにすべてのイベントを待機スレッド設定します。 |
|
イベント オブジェクトを解放します。 |
解説
イベントは、スレッドがタスクを実行するタイミングを知る必要がある場合に役立ちます。たとえば、データをデータ アーカイブにコピーするスレッドは、新しいデータが利用できるようになったときに通知される必要があります。新しいデータが利用できるようになったとき、CEvent オブジェクトを使ってコピーを行うスレッドに通知をすると、スレッドはすぐにコピーを行うことができます。
CEvent オブジェクトには、手動と自動の 2 つの型があります。
自動の CEvent オブジェクトは、少なくとも 1 つのスレッドが解放されると、自動的に非シグナル状態 (利用できない状態) になります。既定では、構築時に bManualReset パラメーターに TRUE を渡さない限り、CEvent オブジェクトは自動になります。
手動の CEvent オブジェクトは、他の関数が呼び出されるまで SetEvent または ResetEvent で設定された状態を維持します。手動の CEvent オブジェクトを作成するには、構築時に bManualReset パラメーターに TRUE を渡します。
CEvent オブジェクトを使用するには、必要になったときに CEvent オブジェクトを構築します。待機するイベント名を指定すると共に、そのイベントを最初はアプリケーションが所有するように指定します。コンストラクターから戻るとイベントにアクセスできます。SetEvent を呼び出してイベント オブジェクトをシグナル状態 (利用できる状態) にします。その後、制御されるリソースへのアクセス終了時に Unlock を呼び出します。
CEvent オブジェクトのもう 1 つの使い方は、制御するクラスのデータ メンバーとして、CEvent 型の変数を追加することです。制御されるオブジェクトの構築中に、CEvent データ メンバーのコンストラクターを呼び出し、イベントを最初にシグナル状態にするかどうか、使用するイベント オブジェクトの型、イベント名 (プロセス境界をまたいで使用する場合)、および必要なセキュリティ属性を指定します。
この方法で CEvent オブジェクトが制御しているリソースにアクセスするには、まず、リソースにアクセスするメソッド内に CSingleLock 型または CMultiLock 型の変数を作成します。次に、ロック オブジェクトの Lock メソッド (たとえば CMultiLock::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
必要条件
ヘッダー : afxmt.h