Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
A biblioteca Microsoft Foundation Classes (MFC) continua a ser suportada. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.
Representa um evento, que é um objeto de sincronização que permite a um thread notificar outro que um evento ocorreu.
Sintaxe
class CEvent : public CSyncObject
Membros
Construtores Públicos
| Nome | Description |
|---|---|
CEvent::CEvent |
Constrói um CEvent objeto. |
Métodos Públicos
| Nome | Description |
|---|---|
CEvent::PulseEvent |
Define o evento como disponível (sinalizado), liberta threads em espera e define o evento como indisponível (não sinalizado). |
CEvent::ResetEvent |
Define o evento para indisponível (não sinalizado). |
CEvent::SetEvent |
Define o evento para disponível (sinalizado) e liberta quaisquer threads em espera. |
CEvent::Unlock |
Liberta o objeto de evento. |
Observações
Os eventos são úteis quando um thread tem de saber quando realizar a sua tarefa. Por exemplo, um thread que copia dados para um arquivo de dados deve ser notificado quando novos dados estiverem disponíveis. Ao usar um CEvent objeto para notificar a thread de cópia quando novos dados estão disponíveis, a thread pode realizar a sua tarefa o mais rapidamente possível.
CEvent Os objetos têm dois tipos: manual e automático.
Um objeto automático CEvent regressa automaticamente a um estado não sinalizado (indisponível) após pelo menos uma thread ser libertada. Por defeito, um CEvent objeto é automático a menos que passe TRUE para o bManualReset parâmetro durante a construção.
Um objeto manual CEvent mantém-se no estado definido por SetEvent ou ResetEvent até que a outra função seja chamada. Para criar um objeto manual CEvent , passe TRUE pelo bManualReset parâmetro durante a construção.
Para usar um CEvent objeto, constrói o CEvent objeto quando for necessário. Especifique o nome do evento pelo qual quer esperar e também que a sua candidatura deve ser inicialmente proprietária. Pode então aceder ao evento quando o construtor regressar. Chama SetEvent para sinalizar (disponibilizar) o objeto de evento e depois liga Unlock quando terminares de aceder ao recurso controlado.
Um método alternativo para usar CEvent objetos é adicionar uma variável do tipo CEvent como membro de dados à classe que pretende controlar. Durante a construção do objeto controlado, chame o construtor do CEvent membro de dados e especifique se o evento é inicialmente sinalizado, e também o tipo de objeto de evento que pretende, o nome do evento (se será usado através dos limites do processo) e quaisquer atributos de segurança que pretenda.
Para aceder a um recurso controlado por um CEvent objeto desta forma, crie primeiro uma variável de qualquer tipo CSingleLock ou tipo CMultiLock no método de acesso do seu recurso. Depois chama o Lock método do lock objeto (por exemplo, CMultiLock::Lock). Neste ponto, o seu thread ou terá acesso ao recurso, esperar que o recurso seja libertado e obter acesso, ou esperar que o recurso seja libertado, perder tempo e falhar em aceder ao recurso. Em todo o caso, o seu recurso foi acedido de forma segura para threads. Para libertar o recurso, chame SetEvent para sinalizar o objeto de evento e depois use o Unlock método do lock objeto (por exemplo, CMultiLock::Unlock), ou deixe o lock objeto sair do âmbito.
Para mais informações sobre como usar CEvent objetos, consulte Multithreading: Como Usar as Classes de Sincronização.
Example
// 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
};
Hierarquia de herança
CEvent
Requerimentos
Cabeçalho:afxmt.h
CEvent::CEvent
Constrói um objeto nomeado ou não nomeado CEvent .
CEvent(
BOOL bInitiallyOwn = FALSE,
BOOL bManualReset = FALSE,
LPCTSTR lpszName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);
Parâmetros
bInitiallyOwn
Se TRUE, a thread para o CMultilock objeto ou CSingleLock está ativada. Caso contrário, todos os threads que queiram aceder ao recurso têm de esperar.
bManualReset
Se TRUE, especificar que o objeto evento é um evento manual, caso contrário o objeto evento é um evento automático.
lpszName
Nome do CEvent objeto. Deve ser fornecido se o objeto for usado através dos limites do processo. Se o nome corresponder a um evento existente, o construtor constrói um novo CEvent objeto que faz referência ao evento com esse nome. Se o nome corresponder a um objeto de sincronização existente que não é um evento, a construção falhará. Se NULL, o nome será nulo.
lpsaAttribute
Atributos de segurança para o objeto de evento. Para uma descrição completa desta estrutura, veja SECURITY_ATTRIBUTES no SDK do Windows.
Observações
Para aceder ou libertar um CEvent objeto, crie um CMultiLock objeto ou CSingleLock e chame as suas Lock funções membros Unlock .
Para alterar o estado de um CEvent objeto para sinalizado (os threads não têm de esperar), chame SetEvent ou PulseEvent. Para definir o estado de um CEvent objeto para não sinalizado (os threads têm de esperar), chame ResetEvent.
Importante
Depois de criar o CEvent objeto, use GetLastError para garantir que o mutex não existia antes. Se o mutex existiu inesperadamente, pode indicar que um processo desonesto está a ocupar e pode estar a tentar usar o mutex de forma maliciosa. Neste caso, o procedimento recomendado, consciente da segurança, é fechar a maçaneta e continuar como se houvesse uma falha na criação do objeto.
CEvent::PulseEvent
Define o estado do evento para sinalizado (disponível), liberta quaisquer threads em espera e reinicia automaticamente para não sinalizado (indisponível).
BOOL PulseEvent();
Valor de retorno
Não nula se a função fosse bem-sucedida; caso contrário, 0.
Observações
Se o evento for manual, todos os threads em espera são libertados, o evento é definido como não sinalizado e PulseEvent retorna. Se o evento for automático, um único thread é libertado, o evento é definido como não sinalizado e PulseEvent retorna.
Se não houver threads à espera, ou se nenhum thread puder ser libertado imediatamente, PulseEvent define o estado do evento para não sinalizado e retorna.
PulseEvent utiliza a função Win32 PulseEvent subjacente, que pode ser momentaneamente removida do estado de espera por uma chamada de procedimento assíncrona em modo kernel. Por isso, PulseEvent é pouco fiável e não deve ser usado por novas aplicações. Para obter mais informações, consulte a PulseEvent função.
CEvent::ResetEvent
Define o estado do evento como não sinalizado até ser explicitamente definido como sinalizado pela SetEvent função membro.
BOOL ResetEvent();
Valor de retorno
Não nula se a função fosse bem-sucedida; caso contrário, 0.
Observações
Isto faz com que todos os tópicos que desejam aceder a este evento aguardem.
Esta função de membro não é usada por eventos automáticos.
CEvent::SetEvent
Define o estado do evento para sinalizado, libertando quaisquer threads em espera.
BOOL SetEvent();
Valor de retorno
Diferente de zero se a função fosse bem-sucedida, caso contrário 0.
Observações
Se o evento for manual, o evento permanecerá sinalizado até ResetEvent ser chamado. Mais do que um tópico pode ser divulgado neste caso. Se o evento for automático, o evento permanecerá sinalizado até que um único thread seja libertado. O sistema então define o estado do evento para não sinalizado. Se não houver threads à espera, o estado permanece sinalizado até que um thread seja libertado.
CEvent::Unlock
Liberta o objeto de evento.
BOOL Unlock();
Valor de retorno
Diferente de zero se o thread fosse proprietário do objeto evento e o evento for um evento automático; caso contrário, 0.
Observações
Esta função membro é chamada por threads que atualmente possuem um evento automático para a libertar depois de terminarem, caso o seu lock objeto seja reutilizado. Se o lock objeto não for para ser reutilizado, esta função será chamada pelo lock destruidor do objeto.