CEvent クラス

イベントを表します。これは、あるスレッドから別のスレッドにイベントの発生を通知できるようにする同期オブジェクトです。

class CEvent : public CSyncObject

解説

イベントは、スレッドがタスクを実行するタイミングを知る必要がある場合に役立ちます。 たとえば、データをデータ アーカイブにコピーするスレッドは、新しいデータが利用できるようになったときに通知される必要があります。 新しいデータが利用できるようになったとき、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
};

必要条件

**ヘッダー:**afxmt.h

参照

参照

CSyncObject クラス

階層図

その他の技術情報

CEvent のメンバー