CEvent Klasa

Reprezentuje zdarzenie, które jest obiektem synchronizacji, który umożliwia jednemu wątkowi powiadamianie innego o wystąpieniu zdarzenia.

Składnia

class CEvent : public CSyncObject

Członkowie

Konstruktory publiczne

Nazwa/nazwisko opis
CEvent::CEvent CEvent Tworzy obiekt.

Metody publiczne

Nazwa/nazwisko opis
CEvent::PulseEvent Ustawia zdarzenie na dostępne (sygnaliowane), zwalnia oczekujące wątki i ustawia zdarzenie na niedostępne (niepodpisane).
CEvent::ResetEvent Ustawia zdarzenie na niedostępne (niepodpisane).
CEvent::SetEvent Ustawia zdarzenie na dostępne (zasygnaliowane) i zwalnia wszystkie oczekujące wątki.
CEvent::Unlock Zwalnia obiekt zdarzenia.

Uwagi

Zdarzenia są przydatne, gdy wątek musi wiedzieć, kiedy należy wykonać zadanie. Na przykład wątek, który kopiuje dane do archiwum danych, musi być powiadamiany o dostępności nowych danych. Za pomocą CEvent obiektu w celu powiadomienia wątku kopiowania, gdy są dostępne nowe dane, wątek może wykonać swoje zadanie tak szybko, jak to możliwe.

CEvent obiekty mają dwa typy: ręczne i automatyczne.

Obiekt automatyczny CEvent automatycznie powraca do stanu niesygnalizowanego (niedostępnego) po wydaniu co najmniej jednego wątku. Domyślnie obiekt jest automatyczny, CEvent chyba że zostanie przekazany TRUEbManualReset parametr podczas budowy.

Obiekt ręczny CEvent pozostaje w stanie ustawionym przez SetEvent lub ResetEvent do momentu wywołania innej funkcji. Aby utworzyć obiekt ręczny CEvent , przekaż TRUE parametr dla parametru bManualReset podczas budowy.

Aby użyć CEvent obiektu, skonstruuj CEvent obiekt, gdy jest wymagany. Określ nazwę zdarzenia, które chcesz zaczekać, a także określ, że aplikacja powinna być jej właścicielem. Następnie możesz uzyskać dostęp do zdarzenia po powrocie konstruktora. Wywołaj SetEvent metodę sygnału (udostępnij) obiekt zdarzenia, a następnie wywołaj Unlock metodę po zakończeniu uzyskiwania dostępu do kontrolowanego zasobu.

Alternatywną metodą używania CEvent obiektów jest dodanie zmiennej typu CEvent jako składowej danych do klasy, którą chcesz kontrolować. Podczas konstruowania kontrolowanego obiektu wywołaj konstruktor CEvent elementu członkowskiego danych i określ, czy zdarzenie jest początkowo sygnalizowane, a także określ typ żądanego obiektu zdarzenia, nazwę zdarzenia (jeśli zostanie ono użyte przez granice procesu) oraz wszelkie żądane atrybuty zabezpieczeń.

Aby uzyskać dostęp do zasobu kontrolowanego CEvent przez obiekt w ten sposób, najpierw utwórz zmienną typu CSingleLock lub typu CMultiLock w metodzie dostępu zasobu. Następnie wywołaj metodę Locklock obiektu (na przykład CMultiLock::Lock). W tym momencie wątek uzyska dostęp do zasobu, zaczekaj na zwolnienie i uzyskanie dostępu do zasobu albo poczekaj na zwolnienie, przekroczenie limitu czasu i uzyskanie dostępu do zasobu. W każdym razie zasób został dostępny w bezpieczny wątkowo sposób. Aby zwolnić zasób, wywołaj metodę SetEvent , aby zasygnalizować obiekt zdarzenia, a następnie użyć Unlock metody lock obiektu (na przykład CMultiLock::Unlock), lub niech lock obiekt wypadnie z zakresu.

Aby uzyskać więcej informacji na temat używania obiektów, zobacz Multithreading: How to Use the Synchronization Classes (Jak używać CEvent klas synchronizacji).

Przykład

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

Hierarchia dziedziczenia

Cobject

CSyncObject

CEvent

Wymagania

Nagłówka:afxmt.h

CEvent::CEvent

Tworzy nazwany lub nienazwany CEvent obiekt.

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

Parametry

bInitiallyOwn
Jeśli TRUEwątek dla CMultilock obiektu lub CSingleLock jest włączony. W przeciwnym razie wszystkie wątki, które chcą uzyskać dostęp do zasobu, muszą czekać.

bManualReset
Jeśli TRUEparametr określa, że obiekt zdarzenia jest zdarzeniem ręcznym, w przeciwnym razie obiekt zdarzenia jest zdarzeniem automatycznym.

lpszName
CEvent Nazwa obiektu. Należy podać, jeśli obiekt będzie używany przez granice procesu. Jeśli nazwa jest zgodna z istniejącym zdarzeniem, konstruktor tworzy nowy CEvent obiekt odwołujący się do zdarzenia tej nazwy. Jeśli nazwa jest zgodna z istniejącym obiektem synchronizacji, który nie jest zdarzeniem, konstrukcja zakończy się niepowodzeniem. Jeśli NULLnazwa będzie mieć wartość null.

lpsaAttribute
Atrybuty zabezpieczeń obiektu zdarzenia. Pełny opis tej struktury można znaleźć SECURITY_ATTRIBUTES w zestawie Windows SDK.

Uwagi

Aby uzyskać dostęp do obiektu lub zwolnić CEvent go, utwórz CMultiLock obiekt lub CSingleLock i wywołaj jego Lock funkcje składowe i Unlock .

Aby zmienić stan CEvent obiektu na zasygnalizowany (wątki nie muszą czekać), wywołanie SetEvent lub PulseEvent. Aby ustawić stan obiektu na niepodpisany (wątki muszą czekać), wywołaj metodę CEventResetEvent.

Ważne

Po utworzeniu CEvent obiektu użyj polecenia GetLastError , aby upewnić się, że mutex jeszcze nie istnieje. Jeśli mutex nie istnieje nieoczekiwanie, może wskazywać, że nieuczciwy proces kuca i może być zamierza użyć mutex złośliwie. W takim przypadku zalecaną procedurą świadomą zabezpieczeń jest zamknięcie uchwytu i kontynuowanie tak, jakby wystąpił błąd podczas tworzenia obiektu.

CEvent::PulseEvent

Ustawia stan zdarzenia na sygnał (dostępny), zwalnia wszystkie oczekujące wątki i resetuje je automatycznie do niepodpisanych (niedostępnych).

BOOL PulseEvent();

Wartość zwracana

Nonzero, jeśli funkcja zakończyła się pomyślnie; w przeciwnym razie 0.

Uwagi

Jeśli zdarzenie jest ręczne, wszystkie wątki oczekujące są zwalniane, zdarzenie jest ustawione na niepodpisane i PulseEvent zwraca. Jeśli zdarzenie jest automatyczne, pojedynczy wątek jest zwalniany, zdarzenie jest ustawione na niepodpisane i PulseEvent zwraca.

Jeśli wątki nie oczekują lub nie można natychmiast zwolnić wątków, PulseEvent ustawia stan zdarzenia na niepodpisany i zwraca.

PulseEvent używa podstawowej funkcji Win32 PulseEvent , która może zostać chwilowo usunięta ze stanu oczekiwania przez wywołanie asynchronicznej procedury trybu jądra. PulseEvent W związku z tym nie jest zawodny i nie powinien być używany przez nowe aplikacje. Aby uzyskać więcej informacji, zobacz PulseEvent funkcję .

CEvent::ResetEvent

Ustawia stan zdarzenia na niepodpisany, dopóki nie zostanie jawnie ustawiony na sygnalizowany przez funkcję składową SetEvent .

BOOL ResetEvent();

Wartość zwracana

Nonzero, jeśli funkcja zakończyła się pomyślnie; w przeciwnym razie 0.

Uwagi

Powoduje to, że wszystkie wątki, które chcą uzyskać dostęp do tego zdarzenia, będą czekać.

Ta funkcja składowa nie jest używana przez zdarzenia automatyczne.

CEvent::SetEvent

Ustawia stan zdarzenia na sygnał, zwalniając wszystkie oczekujące wątki.

BOOL SetEvent();

Wartość zwracana

Nonzero, jeśli funkcja zakończyła się pomyślnie, w przeciwnym razie 0.

Uwagi

Jeśli zdarzenie jest ręczne, zdarzenie pozostanie zasygnalizowane do momentu ResetEvent wywołania. W tym przypadku można zwolnić więcej niż jeden wątek. Jeśli zdarzenie jest automatyczne, zdarzenie pozostanie zasygnalizowane do momentu wydania pojedynczego wątku. Następnie system ustawi stan zdarzenia na niepodpisany. Jeśli wątki nie czekają, stan pozostaje zasygnalizowany do momentu zwolnienia jednego wątku.

CEvent::Unlock

Zwalnia obiekt zdarzenia.

BOOL Unlock();

Wartość zwracana

Niezerowe, jeśli wątek posiadał obiekt zdarzenia, a zdarzenie jest zdarzeniem automatycznym; w przeciwnym razie 0.

Uwagi

Ta funkcja składowa jest wywoływana przez wątki, które są obecnie właścicielem zdarzenia automatycznego, aby zwolnić je po zakończeniu, jeśli ich lock obiekt ma zostać ponownie użyty. lock Jeśli obiekt nie ma być ponownie używany, ta funkcja zostanie wywołana przez lock destruktor obiektu.

Zobacz też

CSyncObject Klasa
Wykres hierarchii