共用方式為


CEvent 類別

表示事件,這是一個同步處理物件,可讓一個執行緒通知另一個事件已發生。

語法

class CEvent : public CSyncObject

成員

公用建構函式

名稱 描述
CEvent::CEvent 建構 CEvent 物件。

公用方法

名稱 描述
CEvent::PulseEvent 將事件設定為可用(已發出訊號)、釋放等候的執行緒,並將事件設定為無法使用(未簽署)。
CEvent::ResetEvent 將事件設定為無法使用(未簽署)。
CEvent::SetEvent 將事件設定為可用(已發出訊號),並釋放任何等候的執行緒。
CEvent::Unlock 釋放事件物件。

備註

當執行緒必須知道何時執行其工作時,事件會很有用。 例如,將資料複製到資料封存的執行緒必須在有新資料可用時收到通知。 藉由使用 CEvent 物件在有新資料可用時通知複製執行緒,執行緒可以儘快執行其工作。

CEvent 物件有兩種類型:手動和自動。

至少釋放一個執行緒之後,自動 CEvent 物件會自動回到非訊號(無法使用)狀態。 根據預設, CEvent 除非您在建構期間傳遞 TRUE 參數,否則物件是自動的 bManualReset

手動 CEvent 物件會留在 或 ResetEventSetEvent 設定的狀態中,直到呼叫其他函式為止。 若要建立手動 CEvent 物件,請在建構期間傳遞 TRUEbManualReset 參數。

若要使用 CEvent 物件,請在需要時建構 CEvent 物件。 指定您想要等候的事件名稱,並指定應用程式應該一開始擁有它。 接著,您可以在建構函式傳回時存取 事件。 呼叫 SetEvent 以發出訊號(讓可用)事件物件,然後在您完成存取受控制資源時呼叫 Unlock

使用 CEvent 物件的替代方法是將 型 CEvent 別的變數新增為您想要控制之類別的資料成員。 在建構受控制物件期間,呼叫資料成員的 CEvent 建構函式,並指定事件是否一開始發出訊號,同時指定您想要的事件物件類型、事件的名稱(如果它會跨進程界限使用),以及您想要的任何安全性屬性。

若要以這種方式存取物件所 CEvent 控制的資源,請先在資源的存取方法中建立類型 CSingleLock 或類型的 CMultiLock 變數。 然後呼叫 Lock 物件的 方法 lock (例如 , CMultiLock::Lock 。 此時,您的執行緒會取得資源的存取權、等候釋放資源並取得存取權,或等候資源釋放、逾時,以及無法取得資源的存取權。 在任何情況下,您的資源都已以安全線程的方式存取。 若要釋放資源,請呼叫 SetEvent 來發出事件物件的訊號,然後使用 Unlock 物件的 方法 lock (例如 CMultiLock::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
};

繼承階層架構

CObject

CSyncObject

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
事件物件的安全性屬性。 如需此結構的完整描述,請參閱 SECURITY_ATTRIBUTES Windows SDK。

備註

若要存取或釋放 CEvent 物件,請建立 CMultiLockCSingleLock 物件並呼叫其 LockUnlock 成員函式。

若要將物件的狀態 CEvent 變更為已發出訊號(執行緒不需要等候),請呼叫 SetEventPulseEvent 。 若要將 物件的狀態 CEvent 設定為非對齊狀態(執行緒必須等候),請呼叫 ResetEvent

重要

建立 CEvent 物件之後,請使用 GetLastError 來確保 mutex 不存在。 如果 Mutex 確實出人意料地存在,則可能表示惡意程式正在蹲下,而且可能打算惡意使用 Mutex。 在此情況下,建議的安全性意識程式是關閉控制碼並繼續,就像建立物件時發生失敗一樣。

CEvent::PulseEvent

將事件的狀態設定為已發出訊號(可用)、釋放任何等候的執行緒,並將它自動重設為非信號(無法使用)。

BOOL PulseEvent();

傳回值

如果函式成功,則為非零;否則為 0。

備註

如果事件是手動的,所有等候的執行緒都會釋放,事件會設定為非對齊,並 PulseEvent 傳回 。 如果事件為自動,則會釋放單一線程,事件會設定為非對齊,並 PulseEvent 傳回 。

如果沒有線程正在等候,或無法立即釋放執行緒, PulseEvent 請將事件的狀態設定為未簽署並傳回。

PulseEvent 會使用基礎 Win32 PulseEvent 函式,此函式可透過核心模式非同步程序呼叫暫時從等候狀態中移除。 因此, PulseEvent 是不可靠的,不應該由新的應用程式使用。 如需詳細資訊,請參閱 函式 PulseEvent

CEvent::ResetEvent

將事件的狀態設定為非信號,直到明確設定為成員函式所發出訊號為止 SetEvent

BOOL ResetEvent();

傳回值

如果函式成功,則為非零;否則為 0。

備註

這會導致所有想要存取此事件的執行緒等候。

自動事件不會使用此成員函式。

CEvent::SetEvent

將事件的狀態設定為已發出訊號,釋放任何等候的執行緒。

BOOL SetEvent();

傳回值

如果函式成功,則為非零,否則為 0。

備註

如果事件是手動的,事件會保持訊號,直到呼叫為止 ResetEvent 。 在此情況下,可以釋放多個執行緒。 如果事件為自動,事件會保持訊號,直到釋放單一線程為止。 系統接著會將事件的狀態設定為非對齊狀態。 如果沒有線程正在等候,狀態會維持訊號,直到釋放一個執行緒為止。

CEvent::Unlock

釋放事件物件。

BOOL Unlock();

傳回值

如果執行緒擁有事件物件且事件是自動事件,則為非零;否則為 0。

備註

如果執行緒的物件是重複使用,則此成員函式是由目前擁有自動事件而擁有的執行緒所呼叫, lock 以便在完成之後釋放該函式。 lock如果物件不重複使用,物件解構函式將會呼叫 lock 此函式。

另請參閱

CSyncObject
階層架構圖表