Share via


La classe CEvent

Représente un événement, qui est un objet de synchronisation qui permet à un thread d’avertir un autre qu’un événement s’est produit.

Syntaxe

class CEvent : public CSyncObject

Membres

Constructeurs publics

Nom Description
CEvent::CEvent Construit un objet CEvent.

Méthodes publiques

Nom Description
CEvent::PulseEvent Définit l’événement sur disponible (signalé), libère les threads en attente et définit l’événement sur indisponible (non signé).
CEvent::ResetEvent Définit l’événement sur non disponible (non signé).
CEvent::SetEvent Définit l’événement sur disponible (signalé) et libère tous les threads en attente.
CEvent::Unlock Libère l’objet d’événement.

Notes

Les événements sont utiles lorsqu’un thread doit savoir quand effectuer sa tâche. Par exemple, un thread qui copie des données dans une archive de données doit être averti lorsque de nouvelles données sont disponibles. En utilisant un CEvent objet pour notifier le thread de copie lorsque de nouvelles données sont disponibles, le thread peut effectuer sa tâche dès que possible.

CEvent les objets ont deux types : manuel et automatique.

Un objet automatique CEvent revient automatiquement à un état non signalé (indisponible) une fois qu’au moins un thread est libéré. Par défaut, un CEvent objet est automatique, sauf si vous passez TRUE le paramètre pendant la bManualReset construction.

Un objet manuel CEvent reste dans l’état défini par SetEvent ou ResetEvent jusqu’à ce que l’autre fonction soit appelée. Pour créer un objet manuel CEvent , passez TRUE le paramètre pendant la bManualReset construction.

Pour utiliser un CEvent objet, construisez l’objet CEvent lorsqu’il est requis. Spécifiez le nom de l’événement sur lequel vous souhaitez attendre et spécifiez également que votre application doit la posséder initialement. Vous pouvez ensuite accéder à l’événement lorsque le constructeur retourne. Appelez SetEvent au signal (rendre disponible) l’objet d’événement, puis appelez Unlock lorsque vous avez terminé d’accéder à la ressource contrôlée.

Une autre méthode pour utiliser CEvent des objets consiste à ajouter une variable de type CEvent en tant que membre de données à la classe que vous souhaitez contrôler. Lors de la construction de l’objet contrôlé, appelez le constructeur du CEvent membre de données et spécifiez si l’événement est initialement signalé et spécifiez également le type d’objet d’événement souhaité, le nom de l’événement (s’il sera utilisé entre les limites du processus) et les attributs de sécurité souhaités.

Pour accéder à une ressource contrôlée par un CEvent objet de cette façon, créez d’abord une variable de type ou de type CSingleLockCMultiLock dans la méthode d’accès de votre ressource. Appelez ensuite la Lock méthode de l’objet lock (par exemple, CMultiLock::Lock). À ce stade, votre thread accède à la ressource, attend que la ressource soit libérée et soit accessible, soit attend que la ressource soit libérée, expire et ne parvient pas à accéder à la ressource. Dans tous les cas, votre ressource a été accessible de manière thread-safe. Pour libérer la ressource, appelez SetEvent pour signaler l’objet d’événement, puis utilisez la Unlock méthode de l’objet lock (par exemple), CMultiLock::Unlockou laissez l’objet lock tomber hors de portée.

Pour plus d’informations sur l’utilisation CEvent d’objets, consultez Multithreading : Utilisation des classes de synchronisation.

Exemple

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

Hiérarchie d'héritage

CObject

CSyncObject

CEvent

Spécifications

En-têteafxmt.h:

CEvent::CEvent

Construit un objet nommé ou non nommé CEvent .

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

Paramètres

bInitiallyOwn
Si TRUE, le thread pour l’objet ou CSingleLock l’objet CMultilock est activé. Sinon, tous les threads qui veulent accéder à la ressource doivent attendre.

bManualReset
Si TRUE, spécifie que l’objet événement est un événement manuel, sinon l’objet événement est un événement automatique.

lpszName
Nom de l'objet CEvent. Doit être fourni si l’objet sera utilisé entre les limites de processus. Si le nom correspond à un événement existant, le constructeur génère un nouvel CEvent objet qui fait référence à l’événement de ce nom. Si le nom correspond à un objet de synchronisation existant qui n’est pas un événement, la construction échoue. Si NULL, le nom est null.

lpsaAttribute
Attributs de sécurité pour l’objet d’événement. Pour obtenir une description complète de cette structure, consultez SECURITY_ATTRIBUTES le Kit de développement logiciel (SDK) Windows.

Notes

Pour accéder ou libérer un CEvent objet, créez un ou CSingleLock un CMultiLock objet et appelez ses fonctions membres et Unlock ses Lock fonctions membres.

Pour changer l’état d’un CEvent objet à signaler (les threads n’ont pas besoin d’attendre), d’appeler SetEvent ou PulseEvent. Pour définir l’état d’un CEvent objet sur non signé (threads doivent attendre), appelez ResetEvent.

Important

Après avoir créé l’objet CEvent , utilisez cette option GetLastError pour vous assurer que le mutex n’existe pas déjà. Si le mutex existait de façon inattendue, il peut indiquer qu’un processus non autorisé est en squattage et qu’il est susceptible d’utiliser le mutex malveillantment. Dans ce cas, la procédure recommandée pour la sécurité consiste à fermer le handle et à continuer comme s’il y avait un échec dans la création de l’objet.

CEvent::PulseEvent

Définit l’état de l’événement à signaler (disponible), libère tous les threads en attente et le réinitialise automatiquement en nonsignaled (indisponible).

BOOL PulseEvent();

Valeur de retour

Différent de zéro si la fonction a réussi ; sinon 0.

Notes

Si l’événement est manuel, tous les threads en attente sont libérés, l’événement est défini sur non signé et PulseEvent retourne. Si l’événement est automatique, un thread unique est libéré, l’événement est défini sur non signé et PulseEvent retourne.

Si aucun thread n’attend, ou qu’aucun thread ne peut être libéré immédiatement, PulseEvent définit l’état de l’événement sur non signé et retourne.

PulseEvent utilise la fonction Win32 PulseEvent sous-jacente, qui peut être temporairement supprimée de l’état d’attente par un appel de procédure asynchrone en mode noyau. Par conséquent, PulseEvent n’est pas fiable et ne doit pas être utilisé par de nouvelles applications. Pour plus d’informations, consultez la PulseEvent fonction.

CEvent::ResetEvent

Définit l’état de l’événement sur non signé jusqu’à ce qu’il soit explicitement défini sur signalé par la SetEvent fonction membre.

BOOL ResetEvent();

Valeur de retour

Différent de zéro si la fonction a réussi ; sinon 0.

Notes

Cela entraîne l’attente de tous les threads souhaitant accéder à cet événement.

Cette fonction membre n’est pas utilisée par les événements automatiques.

CEvent::SetEvent

Définit l’état de l’événement à signaler, en libérant tous les threads en attente.

BOOL SetEvent();

Valeur de retour

Différent de zéro si la fonction a réussi, sinon 0.

Notes

Si l’événement est manuel, l’événement reste signalé jusqu’à ce qu’il ResetEvent soit appelé. Plusieurs threads peuvent être libérés dans ce cas. Si l’événement est automatique, l’événement reste signalé jusqu’à ce qu’un thread unique soit libéré. Le système définit ensuite l’état de l’événement sur non signé. Si aucun thread n’attend, l’état reste signalé jusqu’à ce qu’un thread soit libéré.

CEvent::Unlock

Libère l’objet d’événement.

BOOL Unlock();

Valeur de retour

Différent de zéro si le thread possédait l’objet d’événement et que l’événement est un événement automatique ; sinon 0.

Notes

Cette fonction membre est appelée par des threads qui possèdent actuellement un événement automatique pour le libérer une fois qu’ils ont terminé, si leur lock objet doit être réutilisé. Si l’objet lock n’est pas à réutiliser, cette fonction est appelée par le destructeur de l’objet lock .

Voir aussi

CSyncObject Classe
Graphique hiérarchique