Classe CEvent

Rappresenta un evento, ovvero un oggetto di sincronizzazione che consente a un thread di notificare a un altro che si è verificato un evento.

Sintassi

class CEvent : public CSyncObject

Membri

Costruttori pubblici

Nome Descrizione
CEvent::CEvent Costruisce un oggetto CEvent.

Metodi pubblici

Nome Descrizione
CEvent::PulseEvent Imposta l'evento su disponibile (segnalato), rilascia thread in attesa e imposta l'evento su non disponibile (non firmato).
CEvent::ResetEvent Imposta l'evento su non disponibile (non firmato).
CEvent::SetEvent Imposta l'evento su disponibile (segnalato) e rilascia eventuali thread in attesa.
CEvent::Unlock Rilascia l'oggetto evento.

Osservazioni:

Gli eventi sono utili quando un thread deve sapere quando eseguire l'attività. Ad esempio, un thread che copia i dati in un archivio dati deve ricevere una notifica quando sono disponibili nuovi dati. Usando un CEvent oggetto per notificare al thread di copia quando sono disponibili nuovi dati, il thread può eseguire l'attività il prima possibile.

CEvent gli oggetti hanno due tipi: manuale e automatico.

Un oggetto automatico CEvent torna automaticamente a uno stato non segnalato (non disponibile) dopo il rilascio di almeno un thread. Per impostazione predefinita, un CEvent oggetto è automatico, a meno che non si passi TRUE per il parametro durante la bManualReset costruzione.

Un oggetto manuale CEvent rimane nello stato impostato da SetEvent o ResetEvent fino a quando non viene chiamata l'altra funzione. Per creare un oggetto manuale CEvent , passare TRUE per il parametro durante la bManualReset costruzione.

Per usare un CEvent oggetto , costruire l'oggetto CEvent quando necessario. Specificare il nome dell'evento che si vuole attendere e specificare anche che l'applicazione deve essere proprietaria inizialmente. È quindi possibile accedere all'evento quando viene restituito il costruttore. Chiamare SetEvent per segnalare (rendere disponibile) l'oggetto evento e quindi chiamare Unlock al termine dell'accesso alla risorsa controllata.

Un metodo alternativo per l'uso CEvent degli oggetti consiste nell'aggiungere una variabile di tipo CEvent come membro dati alla classe che si desidera controllare. Durante la costruzione dell'oggetto controllato, chiamare il costruttore del CEvent membro dati e specificare se l'evento viene inizialmente segnalato e specificare anche il tipo di oggetto evento desiderato, il nome dell'evento (se verrà usato attraverso i limiti del processo) e gli attributi di sicurezza desiderati.

Per accedere a una risorsa controllata da un CEvent oggetto in questo modo, creare prima di tutto una variabile di tipo o di tipo CSingleLock CMultiLock nel metodo di accesso della risorsa. Chiamare quindi il Lock metodo dell'oggetto lock , ad esempio CMultiLock::Lock. A questo punto, il thread otterrà l'accesso alla risorsa, attenderà il rilascio della risorsa e otterrà l'accesso o attenderà il rilascio della risorsa, il timeout e non riuscirà ad accedere alla risorsa. In ogni caso, la risorsa è stata accessibile in modo thread-safe. Per rilasciare la risorsa, chiamare SetEvent per segnalare l'oggetto evento e quindi usare il Unlock metodo dell'oggetto ,ad esempio CMultiLock::Unlock, oppure lasciare che l'oggetto non sia compreso nell'ambito lock lock.

Per altre informazioni su come usare CEvent gli oggetti, vedere Multithreading: Come usare le classi di sincronizzazione.

Esempio

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

Gerarchia di ereditarietà

CObject

CSyncObject

CEvent

Requisiti

Intestazione: afxmt.h

CEvent::CEvent

Costruisce un oggetto denominato o senza CEvent nome.

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

Parametri

bInitiallyOwn
Se TRUE, il thread per l'oggetto CMultilock o CSingleLock è abilitato. In caso contrario, tutti i thread che desiderano accedere alla risorsa devono attendere.

bManualReset
Se TRUE, specifica che l'oggetto evento è un evento manuale, in caso contrario l'oggetto evento è un evento automatico.

lpszName
Nome dell'oggetto CEvent. Deve essere fornito se l'oggetto verrà usato oltre i limiti del processo. Se il nome corrisponde a un evento esistente, il costruttore compila un nuovo CEvent oggetto che fa riferimento all'evento di tale nome. Se il nome corrisponde a un oggetto di sincronizzazione esistente che non è un evento, la costruzione avrà esito negativo. Se NULL, il nome sarà Null.

lpsaAttribute
Attributi di sicurezza per l'oggetto evento. Per una descrizione completa di questa struttura, vedere SECURITY_ATTRIBUTES in Windows SDK.

Osservazioni:

Per accedere o rilasciare un oggetto , creare un CEvent CMultiLock oggetto o CSingleLock e chiamarne Lock le funzioni membro e Unlock .

Per modificare lo stato di un CEvent oggetto in segnalato (i thread non devono attendere), chiamare SetEvent o PulseEvent. Per impostare lo stato di un CEvent oggetto su non firmato (i thread devono attendere), chiamare ResetEvent.

Importante

Dopo aver creato l'oggetto CEvent , usare GetLastError per assicurarsi che il mutex non esista già. Se il mutex esiste in modo imprevisto, potrebbe indicare che un processo non autorizzato è squatting e potrebbe voler usare il mutex in modo dannoso. In questo caso, la procedura consigliata per la sicurezza consiste nel chiudere l'handle e continuare come se si verificasse un errore nella creazione dell'oggetto.

CEvent::PulseEvent

Imposta lo stato dell'evento su segnalato (disponibile), rilascia tutti i thread in attesa e lo reimposta automaticamente su non firmato (non disponibile).

BOOL PulseEvent();

Valore restituito

Diverso da zero se la funzione ha avuto esito positivo; in caso contrario, 0.

Osservazioni:

Se l'evento è manuale, vengono rilasciati tutti i thread in attesa, l'evento viene impostato su non firmato e PulseEvent restituisce . Se l'evento è automatico, viene rilasciato un singolo thread, l'evento viene impostato su non firmato e PulseEvent restituisce .

Se nessun thread è in attesa o non è possibile rilasciare immediatamente thread, PulseEvent imposta lo stato dell'evento su nonsignaled e restituisce.

PulseEvent usa la funzione Win32 PulseEvent sottostante, che può essere momentaneamente rimossa dallo stato di attesa da una chiamata di procedura asincrona in modalità kernel. Pertanto, PulseEvent non è affidabile e non deve essere usato dalle nuove applicazioni. Per altre informazioni, vedere la PulseEvent funzione .

CEvent::ResetEvent

Imposta lo stato dell'evento su non firmato fino a quando non viene impostato in modo esplicito su segnalato dalla SetEvent funzione membro.

BOOL ResetEvent();

Valore restituito

Diverso da zero se la funzione ha avuto esito positivo; in caso contrario, 0.

Osservazioni:

In questo modo, tutti i thread che desiderano accedere a questo evento sono in attesa.

Questa funzione membro non viene usata dagli eventi automatici.

CEvent::SetEvent

Imposta lo stato dell'evento su segnalato, rilasciando eventuali thread in attesa.

BOOL SetEvent();

Valore restituito

Diverso da zero se la funzione ha avuto esito positivo; in caso contrario, 0.

Osservazioni:

Se l'evento è manuale, l'evento rimarrà segnalato fino a quando ResetEvent non viene chiamato. In questo caso è possibile rilasciare più thread. Se l'evento è automatico, l'evento rimarrà segnalato fino al rilascio di un singolo thread. Il sistema imposta quindi lo stato dell'evento su non firmato. Se non sono in attesa thread, lo stato rimane segnalato fino a quando non viene rilasciato un thread.

CEvent::Unlock

Rilascia l'oggetto evento.

BOOL Unlock();

Valore restituito

Diverso da zero se il thread appartiene all'oggetto evento e l'evento è un evento automatico; in caso contrario, 0.

Osservazioni:

Questa funzione membro viene chiamata dai thread che attualmente possiedono un evento automatico per rilasciarlo al termine, se il relativo lock oggetto deve essere riutilizzato. Se l'oggetto lock non deve essere riutilizzato, questa funzione verrà chiamata dal lock distruttore dell'oggetto.

Vedi anche

CSyncObject Classe
Grafico della gerarchia