CEvent-Klasse
Stellt ein Ereignis dar, das ein Synchronisierungsobjekt, das einen Thread ermöglicht, andere zu benachrichtigen, dass ein Ereignis aufgetreten ist.
class CEvent : public CSyncObject
Mitglieder
Öffentliche Konstruktoren
Name |
Description |
---|---|
Erstellt ein CEvent-Objekt. |
Öffentliche Methoden
Name |
Description |
---|---|
Legt das Ereignis zu verfügbarem (signalisiert), die Versionen, die Threads warten, und die für das Ereignis zu nicht verfügbaren fest (nicht signalisiert). |
|
Legt das Ereignis zu nicht verfügbaren fest (nicht signalisiert). |
|
Legt das Ereignis zu verfügbarem (signalisiert) und - Versionen alle wartenden Threads fest. |
|
Gibt das Ereignisobjekt frei. |
Hinweise
Ereignisse sind nützlich, wenn ein Thread muss wissen, wann die Aufgabe ausführt. Beispielsweise muss ein Thread, der Daten an ein Datenarchiv kopiert, benachrichtigt, wenn neue Daten verfügbar sind. Indem Sie ein CEvent-Objekt verwenden, um die Kopie zu benachrichtigen, dennoch Sie, wenn neue Daten verfügbar sind, der Thread kann seine Aufgabe so schnell wie möglich ausführen.
CEvent-Objekte haben zwei Typen: manuell und automatisch.
Ein automatisches CEvent-Objekt gibt automatisch in einen nicht signalisierten (nicht verfügbaren) Zustand zurück, nachdem mindestens ein Thread freigegeben ist. Standardmäßig ist ein CEvent-Objekt automatisch, es sei denn, Sie TRUE für den bManualReset-Parameter während der Erstellung übergeben.
Ein manuelles CEvent-Objekt verbleibt im Zustand, der von SetEvent oder ResetEvent, bis die andere Funktion festgelegt ist, wird aufgerufen. Um ein manuelles CEvent-Objekt zu erstellen, führen Sie TRUE für den bManualReset-Parameter während der Erstellung.
Um ein CEvent-Objekt zu verwenden, erstellen Sie das Objekt CEvent lassen. Geben Sie den Namen des Ereignisses, das Sie an warten möchten, und geben Sie auch an, dass die Anwendung es zuerst besitzen soll. Sie können auf das Ereignis dann zugreifen, wenn der Konstruktor zurückkehrt. Rufen Sie auf, um SetEvent (), stellen Sie dem bereit Ereignisobjekt signalisieren und Entsperren Sie aufzurufen, wenn Sie auf die gesteuerte Ressource Dateizugriff durchgeführt werden.
Eine alternative Methode für die Verwendung von CEvent-Objekten ist, eine Variable des Typs CEvent hinzuzufügen, wie ein Datenmember für die Klasse, die Sie steuern möchten. Während der Erstellung des Objekts gesteuerten, rufen Sie den Konstruktor des CEvent Datenmembers auf und geben Sie, ob das Ereignis zuerst signalisiert wird, und auch specifythe Typ des Ereignisobjekts, das gewünschte, der Name des Ereignisses (wenn über Prozessgrenzen verwendet wird) und alle gewünschten Sicherheitsattribute an.
Um auf eine Ressource zuzugreifen, die auf diese Weise durch ein CEvent-Objekt gesteuert wird, erstellen Sie entweder eine Variable des Typs CSingleLock oder geben Sie CMultiLock in der Zugriffsmethode der Ressource ein. Rufen Sie dann die Methode des Lock Sperrenobjekts auf (beispielsweise, CMultiLock::Lock). An diesem Punkt wird der Thread entweder auf die Ressource zugreifen, wartet die Ressource freigegeben werden und erhält Zugriff oder die Wartung freigegeben werden, Ressource, Timeout, und auf Fehler, die Ressource zu erhalten. In jedem Fall ist auf die Ressource in eine threadsichere zugegriffen wurde. Um die Ressource freigegeben wird, rufen Sie SetEvent auf die dem Ereignisobjekt zu signalisieren, und verwenden Sie anschließend die Methode des Unlock Sperrenobjekts (beispielsweise, CMultiLock::Unlock), oder Sie können die Sperre Fall außerhalb des gültigen Bereichs Objekts.
Weitere Informationen dazu, wie CEvent-Objekte, finden Sie unter Multithreading: Verwendungsweise der Synchronisierungsklassen verwendet.
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 calulate 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
CEvent
Anforderungen
Header: afxmt.h