CEvent-Klasse

Stellt ein Ereignis dar, bei dem es sich um ein Synchronisierungsobjekt handelt, das es einem Thread ermöglicht, einen anderen darüber zu benachrichtigen, dass ein Ereignis aufgetreten ist.

Syntax

class CEvent : public CSyncObject

Member

Öffentliche Konstruktoren

Name Beschreibung
CEvent::CEvent Erstellt ein CEvent-Objekt.

Öffentliche Methoden

Name Beschreibung
CEvent::PulseEvent Legt das Ereignis auf verfügbar (signalisiert) fest, gibt Wartende Threads frei und legt das Ereignis auf nicht verfügbar (nicht signalisiert) fest.
CEvent::ResetEvent Legt das Ereignis auf nicht verfügbar (nicht signaliert) fest.
CEvent::SetEvent Legt das Ereignis auf verfügbar (signalisiert) fest und gibt alle wartenden Threads frei.
CEvent::Unlock Gibt das Ereignisobjekt frei.

Hinweise

Ereignisse sind nützlich, wenn ein Thread wissen muss, wann die Aufgabe ausgeführt werden soll. Beispielsweise muss ein Thread, der Daten in ein Datenarchiv kopiert, benachrichtigt werden, wenn neue Daten verfügbar sind. Durch Die Verwendung eines CEvent Objekts, um den Kopierthread zu benachrichtigen, wenn neue Daten verfügbar sind, kann der Thread seine Aufgabe so schnell wie möglich ausführen.

CEvent Objekte weisen zwei Typen auf: manuell und automatisch.

Ein automatisches CEvent Objekt kehrt automatisch zu einem nicht signalisierten Zustand (nicht verfügbar) zurück, nachdem mindestens ein Thread losgelassen wurde. Standardmäßig wird ein CEvent Objekt automatisch ausgeführt, es sei denn, Sie übergeben TRUE den Parameter während der bManualReset Konstruktion.

Ein manuelles CEvent Objekt bleibt im Zustand, der von SetEvent oder ResetEvent bis zum Aufruf der anderen Funktion festgelegt ist. Übergeben Sie zum Erstellen eines manuellen CEvent Objekts TRUE den Parameter während der bManualReset Konstruktion.

Um ein CEvent Objekt zu verwenden, erstellen Sie das CEvent Objekt, wenn es erforderlich ist. Geben Sie den Namen des Ereignisses an, das Sie warten möchten, und geben Sie außerdem an, dass die Anwendung sie ursprünglich besitzen soll. Sie können dann auf das Ereignis zugreifen, wenn der Konstruktor zurückgegeben wird. Rufen Sie SetEvent das Ereignisobjekt auf (verfügbar machen), und rufen Sie dann auf Unlock , wenn Sie mit dem Zugriff auf die kontrollierte Ressource fertig sind.

Eine alternative Methode zum Verwenden von CEvent Objekten besteht darin, der Klasse, die Sie steuern möchten, eine Variable vom Typ CEvent als Datenmememm hinzuzufügen. Rufen Sie beim Erstellen des gesteuerten Objekts den Konstruktor des CEvent Datenelements auf, und geben Sie an, ob das Ereignis anfangs signalisiert wird, und geben Sie auch den gewünschten Ereignistyp, den Namen des Ereignisses (sofern es über Prozessgrenzen hinweg verwendet wird) und alle gewünschten Sicherheitsattribute an.

Um auf eine Ressource zuzugreifen, die auf diese Weise von einem CEvent Objekt gesteuert wird, erstellen Sie zuerst eine Variable vom Typ CSingleLock oder Typ CMultiLock in der Zugriffsmethode Ihrer Ressource. Rufen Sie dann die Lock Methode des lock Objekts auf (z. B CMultiLock::Lock. ). An diesem Punkt erhält Ihr Thread entweder Zugriff auf die Ressource, wartet auf die Freigabe der Ressource und erhält Zugriff, oder warten Sie, bis die Ressource freigegeben, timeout ist und keinen Zugriff auf die Ressource erhält. In jedem Fall wurde auf Ihre Ressource auf threadsichere Weise zugegriffen. Um die Ressource freizugeben, rufen Sie SetEvent auf, um das Ereignisobjekt zu signalisieren, und verwenden Sie dann die Unlock Methode des lock Objekts (z. B CMultiLock::Unlock. ), oder lassen Sie das lock Objekt aus dem Bereich herausfallen.

Weitere Informationen zur Verwendung von CEvent Objekten finden Sie unter Multithreading: Verwenden der Synchronisierungsklassen.

Beispiel

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

Vererbungshierarchie

CObject

CSyncObject

CEvent

Anforderungen

Header: afxmt.h

CEvent::CEvent

Erstellt ein benanntes oder nicht benanntes CEvent Objekt.

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

Parameter

bInitiallyOwn
Wenn TRUEder Thread für das CMultilock Objekt CSingleLock aktiviert ist. Andernfalls müssen alle Threads, die auf die Ressource zugreifen möchten, warten.

bManualReset
Wenn TRUE, gibt an, dass das Ereignisobjekt ein manuelles Ereignis ist, andernfalls ist das Ereignisobjekt ein automatisches Ereignis.

lpszName
Name des CEvent-Objekts. Muss angegeben werden, wenn das Objekt über Prozessgrenzen hinweg verwendet wird. Wenn der Name einem vorhandenen Ereignis entspricht, erstellt der Konstruktor ein neues CEvent Objekt, das auf das Ereignis dieses Namens verweist. Wenn der Name einem vorhandenen Synchronisierungsobjekt entspricht, das kein Ereignis ist, schlägt die Konstruktion fehl. If NULL, the name will be null.

lpsaAttribute
Sicherheitsattribute für das Ereignisobjekt. Eine vollständige Beschreibung dieser Struktur finden Sie im SECURITY_ATTRIBUTES Windows SDK.

Hinweise

Um auf ein CEvent Objekt zuzugreifen oder freizugeben, erstellen Sie ein CMultiLock Objekt oder CSingleLock ein Objekt, und rufen Sie dessen Lock Funktionen und Unlock Memberfunktionen auf.

Um den Status eines CEvent Objekts zu ändern, das signalisiert wird (Threads müssen nicht warten), aufrufen SetEvent oder PulseEvent. Rufen Sie auf, um den Status eines CEvent Objekts auf "nichtsignaliert" festzulegen (Threads müssen warten).ResetEvent

Wichtig

Verwenden Sie GetLastError nach dem Erstellen des CEvent Objekts, um sicherzustellen, dass das Mutex noch nicht vorhanden war. Wenn der Mutex unerwartet vorhanden ist, kann es darauf hindeuten, dass ein nicht autorisierter Prozess gleicht und möglicherweise beabsichtigt, den Mutex böswillig zu verwenden. In diesem Fall besteht die empfohlene sicherheitsbewusste Prozedur darin, das Handle zu schließen und fortzusetzen, als ob beim Erstellen des Objekts ein Fehler aufgetreten wäre.

CEvent::PulseEvent

Legt den Status des Ereignisses auf signalisiert (verfügbar) fest, gibt alle Wartethreads frei und setzt ihn automatisch auf nicht signalisiert (nicht verfügbar) zurück.

BOOL PulseEvent();

Rückgabewert

Nonzero, wenn die Funktion erfolgreich war; andernfalls 0.

Hinweise

Wenn das Ereignis manuell ist, werden alle wartenden Threads freigegeben, das Ereignis wird auf nicht signaliert festgelegt und PulseEvent zurückgegeben. Wenn das Ereignis automatisch ausgeführt wird, wird ein einzelner Thread losgelassen, das Ereignis wird auf "nicht signaliert" festgelegt und PulseEvent zurückgegeben.

Wenn keine Threads warten oder keine Threads sofort freigegeben werden können, PulseEvent wird der Status des Ereignisses auf nicht signallos festgelegt und zurückgegeben.

PulseEvent verwendet die zugrunde liegende Win32-Funktion PulseEvent , die von einem asynchronen Prozeduraufruf im Kernelmodus aus dem Wartezustand entfernt werden kann. PulseEvent Daher ist unzuverlässig und sollte nicht von neuen Anwendungen verwendet werden. Weitere Informationen finden Sie unter PulseEvent -Funktion.

CEvent::ResetEvent

Legt den Zustand des Ereignisses auf "nicht signalisiert" fest, bis es explizit auf das Signal der SetEvent Memberfunktion festgelegt ist.

BOOL ResetEvent();

Rückgabewert

Nonzero, wenn die Funktion erfolgreich war; andernfalls 0.

Hinweise

Dies bewirkt, dass alle Threads, die auf dieses Ereignis zugreifen möchten, warten.

Diese Memberfunktion wird nicht von automatischen Ereignissen verwendet.

CEvent::SetEvent

Legt den Status des Ereignisses fest, das signalisiert wird, und gibt alle wartenden Threads frei.

BOOL SetEvent();

Rückgabewert

Nonzero, wenn die Funktion erfolgreich war, andernfalls 0.

Hinweise

Wenn das Ereignis manuell ist, bleibt das Ereignis bis zum ResetEvent Aufrufen signalisiert. In diesem Fall können mehrere Threads freigegeben werden. Wenn das Ereignis automatisch erfolgt, wird das Ereignis bis zur Veröffentlichung eines einzelnen Threads signalisiert. Das System legt dann den Status des Ereignisses auf "Nichtsignal" fest. Wenn keine Threads warten, bleibt der Zustand bis zur Veröffentlichung eines Threads signalisiert.

CEvent::Unlock

Gibt das Ereignisobjekt frei.

BOOL Unlock();

Rückgabewert

Nonzero, wenn der Thread dem Ereignisobjekt gehört und das Ereignis ein automatisches Ereignis ist; andernfalls 0.

Hinweise

Diese Memberfunktion wird von Threads aufgerufen, die derzeit über ein automatisches Ereignis verfügen, um es nach abschluss des Vorgangs freizugeben, wenn ihr lock Objekt wiederverwendet werden soll. Wenn das lock Objekt nicht wiederverwendet werden soll, wird diese Funktion vom Destruktor des lock Objekts aufgerufen.

Siehe auch

CSyncObject Klasse
Hierarchiediagramm