Compartilhar via


Classe CEvent

Representa um "evento" — um objeto de sincronização que permite que um thread notificar outro que um evento ocorreu.

class CEvent : public CSyncObject

Comentários

Eventos são úteis quando um thread precisa saber quando executar sua tarefa.Por exemplo, um thread que copia dados para um arquivar de dados precisaria ser notificado quando novos dados estão disponível.Usando um CEvent objeto para notificar o segmento de cópia quando novos dados estiverem disponível, o thread pode executar sua tarefa assim que possível.

CEvent objetos têm dois tipos: manual e automáticas.Um manual CEvent objeto permanece no estado definido pelo SetEvent or ResetEvent até que a Outros função é chamada.Um automático CEvent objeto retorna automaticamente para um estado nonsignaled (não disponível) após o lançamento de pelo menos um segmento.

Para usar um CEvent objeto, construir o CEvent objeto quando for necessário. Especifique o nome do evento que deseja aguardar e que seu aplicativo deve inicialmente possui.Você pode acessar o evento quando o construtor retorna. De telefonarSetEvent ao sinal (tornar disponível) o objeto de evento e, em seguida, telefonar Desbloquear quando tiver concluído o acesso ao recurso controlado.

Um método alternativo para o uso de CEvent objetos é adicionar uma variável do tipo CEvent sistema autônomo um membro de dados para a classe você deseja controle. Durante a construção do objeto controlado, chama o construtor do CEvent membro de dados especificando se o evento é inicialmente sinalizados, o tipo de evento do objeto desejado, o nome do evento (se ele for usado em limites de processo) e atributos de segurança desejado.

Para acessar um recurso controlado por um CEvent objeto dessa forma, primeiro criar uma variável de qualquer tipo CSingleLock or type CMultiLock na função de membro de acesso do seu recurso.Em seguida, telefonar Lock função de membro (por exemplo, CMultiLock::bloquear).Neste ponto, seu thread irá ou acessar o recurso, aguardar que o recurso ser liberado e obter acesso ou esperar que o recurso a ser liberado e o time limite, que não consegue obter acesso ao recurso.Em qualquer caso, o recurso foi acessado de uma forma thread-safe.Para liberar o recurso, telefonar SetEvent o objeto de evento de sinal e, em seguida, usar o objeto de bloquear Unlock função de membro (por exemplo, CMultiLock::Unlock), ou permitir que o objeto bloquear ficarem fora do escopo.

Para obter mais informações sobre como usar CEvent objetos, consulte o artigo Multithreading: Como usar a sincronização classes.

Exemplo

// 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
};

Requisitos

Cabeçalho: afxmt.h

Consulte também

Referência

Classe CSyncObject

Gráfico de hierarquia

Outros recursos

CEvent membros