Partilhar via


CEvent Classe

Observação

A biblioteca Microsoft Foundation Classes (MFC) continua a ser suportada. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.

Representa um evento, que é um objeto de sincronização que permite a um thread notificar outro que um evento ocorreu.

Sintaxe

class CEvent : public CSyncObject

Membros

Construtores Públicos

Nome Description
CEvent::CEvent Constrói um CEvent objeto.

Métodos Públicos

Nome Description
CEvent::PulseEvent Define o evento como disponível (sinalizado), liberta threads em espera e define o evento como indisponível (não sinalizado).
CEvent::ResetEvent Define o evento para indisponível (não sinalizado).
CEvent::SetEvent Define o evento para disponível (sinalizado) e liberta quaisquer threads em espera.
CEvent::Unlock Liberta o objeto de evento.

Observações

Os eventos são úteis quando um thread tem de saber quando realizar a sua tarefa. Por exemplo, um thread que copia dados para um arquivo de dados deve ser notificado quando novos dados estiverem disponíveis. Ao usar um CEvent objeto para notificar a thread de cópia quando novos dados estão disponíveis, a thread pode realizar a sua tarefa o mais rapidamente possível.

CEvent Os objetos têm dois tipos: manual e automático.

Um objeto automático CEvent regressa automaticamente a um estado não sinalizado (indisponível) após pelo menos uma thread ser libertada. Por defeito, um CEvent objeto é automático a menos que passe TRUE para o bManualReset parâmetro durante a construção.

Um objeto manual CEvent mantém-se no estado definido por SetEvent ou ResetEvent até que a outra função seja chamada. Para criar um objeto manual CEvent , passe TRUE pelo bManualReset parâmetro durante a construção.

Para usar um CEvent objeto, constrói o CEvent objeto quando for necessário. Especifique o nome do evento pelo qual quer esperar e também que a sua candidatura deve ser inicialmente proprietária. Pode então aceder ao evento quando o construtor regressar. Chama SetEvent para sinalizar (disponibilizar) o objeto de evento e depois liga Unlock quando terminares de aceder ao recurso controlado.

Um método alternativo para usar CEvent objetos é adicionar uma variável do tipo CEvent como membro de dados à classe que pretende controlar. Durante a construção do objeto controlado, chame o construtor do CEvent membro de dados e especifique se o evento é inicialmente sinalizado, e também o tipo de objeto de evento que pretende, o nome do evento (se será usado através dos limites do processo) e quaisquer atributos de segurança que pretenda.

Para aceder a um recurso controlado por um CEvent objeto desta forma, crie primeiro uma variável de qualquer tipo CSingleLock ou tipo CMultiLock no método de acesso do seu recurso. Depois chama o Lock método do lock objeto (por exemplo, CMultiLock::Lock). Neste ponto, o seu thread ou terá acesso ao recurso, esperar que o recurso seja libertado e obter acesso, ou esperar que o recurso seja libertado, perder tempo e falhar em aceder ao recurso. Em todo o caso, o seu recurso foi acedido de forma segura para threads. Para libertar o recurso, chame SetEvent para sinalizar o objeto de evento e depois use o Unlock método do lock objeto (por exemplo, CMultiLock::Unlock), ou deixe o lock objeto sair do âmbito.

Para mais informações sobre como usar CEvent objetos, consulte Multithreading: Como Usar as Classes de Sincronização.

Example

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

Hierarquia de herança

CObject

CSyncObject

CEvent

Requerimentos

Cabeçalho:afxmt.h

CEvent::CEvent

Constrói um objeto nomeado ou não nomeado CEvent .

CEvent(
    BOOL bInitiallyOwn = FALSE,
    BOOL bManualReset = FALSE,
    LPCTSTR lpszName = NULL,
    LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);

Parâmetros

bInitiallyOwn
Se TRUE, a thread para o CMultilock objeto ou CSingleLock está ativada. Caso contrário, todos os threads que queiram aceder ao recurso têm de esperar.

bManualReset
Se TRUE, especificar que o objeto evento é um evento manual, caso contrário o objeto evento é um evento automático.

lpszName
Nome do CEvent objeto. Deve ser fornecido se o objeto for usado através dos limites do processo. Se o nome corresponder a um evento existente, o construtor constrói um novo CEvent objeto que faz referência ao evento com esse nome. Se o nome corresponder a um objeto de sincronização existente que não é um evento, a construção falhará. Se NULL, o nome será nulo.

lpsaAttribute
Atributos de segurança para o objeto de evento. Para uma descrição completa desta estrutura, veja SECURITY_ATTRIBUTES no SDK do Windows.

Observações

Para aceder ou libertar um CEvent objeto, crie um CMultiLock objeto ou CSingleLock e chame as suas Lock funções membros Unlock .

Para alterar o estado de um CEvent objeto para sinalizado (os threads não têm de esperar), chame SetEvent ou PulseEvent. Para definir o estado de um CEvent objeto para não sinalizado (os threads têm de esperar), chame ResetEvent.

Importante

Depois de criar o CEvent objeto, use GetLastError para garantir que o mutex não existia antes. Se o mutex existiu inesperadamente, pode indicar que um processo desonesto está a ocupar e pode estar a tentar usar o mutex de forma maliciosa. Neste caso, o procedimento recomendado, consciente da segurança, é fechar a maçaneta e continuar como se houvesse uma falha na criação do objeto.

CEvent::PulseEvent

Define o estado do evento para sinalizado (disponível), liberta quaisquer threads em espera e reinicia automaticamente para não sinalizado (indisponível).

BOOL PulseEvent();

Valor de retorno

Não nula se a função fosse bem-sucedida; caso contrário, 0.

Observações

Se o evento for manual, todos os threads em espera são libertados, o evento é definido como não sinalizado e PulseEvent retorna. Se o evento for automático, um único thread é libertado, o evento é definido como não sinalizado e PulseEvent retorna.

Se não houver threads à espera, ou se nenhum thread puder ser libertado imediatamente, PulseEvent define o estado do evento para não sinalizado e retorna.

PulseEvent utiliza a função Win32 PulseEvent subjacente, que pode ser momentaneamente removida do estado de espera por uma chamada de procedimento assíncrona em modo kernel. Por isso, PulseEvent é pouco fiável e não deve ser usado por novas aplicações. Para obter mais informações, consulte a PulseEvent função.

CEvent::ResetEvent

Define o estado do evento como não sinalizado até ser explicitamente definido como sinalizado pela SetEvent função membro.

BOOL ResetEvent();

Valor de retorno

Não nula se a função fosse bem-sucedida; caso contrário, 0.

Observações

Isto faz com que todos os tópicos que desejam aceder a este evento aguardem.

Esta função de membro não é usada por eventos automáticos.

CEvent::SetEvent

Define o estado do evento para sinalizado, libertando quaisquer threads em espera.

BOOL SetEvent();

Valor de retorno

Diferente de zero se a função fosse bem-sucedida, caso contrário 0.

Observações

Se o evento for manual, o evento permanecerá sinalizado até ResetEvent ser chamado. Mais do que um tópico pode ser divulgado neste caso. Se o evento for automático, o evento permanecerá sinalizado até que um único thread seja libertado. O sistema então define o estado do evento para não sinalizado. Se não houver threads à espera, o estado permanece sinalizado até que um thread seja libertado.

CEvent::Unlock

Liberta o objeto de evento.

BOOL Unlock();

Valor de retorno

Diferente de zero se o thread fosse proprietário do objeto evento e o evento for um evento automático; caso contrário, 0.

Observações

Esta função membro é chamada por threads que atualmente possuem um evento automático para a libertar depois de terminarem, caso o seu lock objeto seja reutilizado. Se o lock objeto não for para ser reutilizado, esta função será chamada pelo lock destruidor do objeto.

Consulte também

CSyncObject Classe
Gráfico de Hierarquia