Compartilhar via


Função WSAWaitForMultipleEvents (winsock2.h)

A função WSAWaitForMultipleEvents retorna quando um ou todos os objetos de evento especificados estão no estado sinalizado, quando o intervalo de tempo limite expira ou quando uma rotina de conclusão de E/S é executada.

Sintaxe

DWORD WSAAPI WSAWaitForMultipleEvents(
  [in] DWORD          cEvents,
  [in] const WSAEVENT *lphEvents,
  [in] BOOL           fWaitAll,
  [in] DWORD          dwTimeout,
  [in] BOOL           fAlertable
);

Parâmetros

[in] cEvents

O número de identificadores de objeto de evento na matriz apontada por lphEvents. O número máximo de identificadores de objeto de evento é WSA_MAXIMUM_WAIT_EVENTS. Um ou mais eventos devem ser especificados.

[in] lphEvents

Um ponteiro para uma matriz de identificadores de objeto de evento. A matriz pode conter identificadores de objetos de diferentes tipos. Ele pode não conter várias cópias do mesmo identificador se o parâmetro fWaitAll estiver definido como TRUE. Se um desses identificadores for fechado enquanto a espera ainda estiver pendente, o comportamento de WSAWaitForMultipleEvents será indefinido.

Os identificadores devem ter o direito de acesso SYNCHRONIZE . Para obter mais informações, consulte Direitos de Acesso Padrão.

[in] fWaitAll

Um valor que especifica o tipo de espera. Se TRUE, a função retornará quando o estado de todos os objetos na matriz lphEvents for sinalizado. Se FALSE, a função retornará quando qualquer um dos objetos de evento for sinalizado. No último caso, o valor retornado menos WSA_WAIT_EVENT_0 indica o índice do objeto de evento cujo estado fez com que a função retornasse. Se mais de um objeto de evento tiver sido sinalizado durante a chamada, esse será o índice de matriz para o objeto de evento sinalizado com o menor valor de índice de todos os objetos de evento sinalizados.

[in] dwTimeout

O intervalo de tempo limite em milissegundos. WSAWaitForMultipleEvents retornará se o intervalo de tempo limite expirar, mesmo que as condições especificadas pelo parâmetro fWaitAll não sejam atendidas. Se o parâmetro dwTimeout for zero, WSAWaitForMultipleEvents testará o estado dos objetos de evento especificados e retornará imediatamente. Se dwTimeout for WSA_INFINITE, WSAWaitForMultipleEvents aguardará para sempre; ou seja, o intervalo de tempo limite nunca expira.

[in] fAlertable

Um valor que especifica se o thread é colocado em um estado de espera alertável para que o sistema possa executar rotinas de conclusão de E/S. Se TRUE, o thread será colocado em um estado de espera alertável e WSAWaitForMultipleEvents poderá retornar quando o sistema executar uma rotina de conclusão de E/S. Nesse caso, WSA_WAIT_IO_COMPLETION é retornado e o evento que estava sendo aguardado ainda não é sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente. Se FALSE, o thread não será colocado em um estado de espera alertável e as rotinas de conclusão de E/S não serão executadas.

Valor retornado

Se a função WSAWaitForMultipleEvents for bem-sucedida, o valor retornado após o sucesso será um dos valores a seguir.

Valor Retornado Significado
WSA_WAIT_EVENT_0 para (WSA_WAIT_EVENT_0 + cEvents – 1)
Se o parâmetro fWaitAll for TRUE, o valor retornado indicará que todos os objetos de evento especificados serão sinalizados.

Se o parâmetro fWaitAll for FALSE, o valor retornado menos WSA_WAIT_EVENT_0 indicará o índice de matriz lphEvents do objeto de evento sinalizado que atendeu à espera. Se mais de um objeto de evento tiver sido sinalizado durante a chamada, o valor retornado indicará o índice de matriz lphEvents do objeto de evento sinalizado com o menor valor de índice de todos os objetos de evento sinalizados.

WSA_WAIT_IO_COMPLETION
A espera foi encerrada por uma ou mais rotinas de conclusão de E/S que foram executadas. O evento que estava sendo aguardado ainda não é sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente. Esse valor retornado só poderá ser retornado se o parâmetro fAlertable for TRUE.
WSA_WAIT_TIMEOUT
O intervalo de tempo limite decorrido e as condições especificadas pelo parâmetro fWaitAll não foram atendidas. Nenhuma rotina de conclusão de E/S foi executada.
 

Se a função WSAWaitForMultipleEvents falhar, o valor retornado será WSA_WAIT_FAILED. A tabela a seguir lista valores que podem ser usados com WSAGetLastError para obter informações de erro estendidas.

Código do erro Significado
WSANOTINITIALISED Uma chamada WSAStartup bem-sucedida deve ocorrer antes de usar essa função.
WSAENETDOWN O subsistema de rede falhou.
WSAEINPROGRESS Uma chamada do Windows Sockets 1.1 de bloqueio está em andamento ou o provedor de serviços ainda está processando uma função de retorno de chamada.
WSA_NOT_ENOUGH_MEMORY Não havia memória livre suficiente disponível para concluir a operação.
WSA_INVALID_HANDLE Um ou mais dos valores na matriz lphEvents não é um identificador de objeto de evento válido.
WSA_INVALID_PARAMETER O parâmetro cEvents não contém uma contagem de identificadores válida.

Comentários

A função WSAWaitForMultipleEvents determina se os critérios de espera foram atendidos. Se os critérios não tiverem sido atendidos, o thread de chamada entrará no estado de espera. Ele não usa tempo de processador enquanto aguarda que os critérios sejam atendidos.

A função WSAWaitForMultipleEvents retorna quando qualquer um ou todos os objetos especificados estão no estado sinalizado ou quando o intervalo de tempo limite passa.

Quando o parâmetro bWaitAll for TRUE, a operação de espera será concluída somente quando os estados de todos os objetos tiverem sido definidos como sinalizados. A função não modifica os estados dos objetos especificados até que os estados de todos os objetos tenham sido definidos como sinalizados.

Quando o parâmetro bWaitAll é FALSE, WSAWaitForMultipleEvents verifica os identificadores na matriz lphEvents para começar com o índice 0, até que um dos objetos seja sinalizado. Se vários objetos forem sinalizados, a função retornará o índice do primeiro identificador na matriz lphEvents cujo objeto foi sinalizado.

Essa função também é usada para executar uma espera alertável definindo o parâmetro fAlertable como TRUE. Isso permite que a função retorne quando o sistema executa uma rotina de conclusão de E/S pelo thread de chamada.

Um thread deve estar em um estado de espera alertável para que o sistema execute rotinas de conclusão de E/S (APCs ou chamadas de procedimento assíncronas). Portanto, se um aplicativo chamar WSAWaitForMultipleEvents quando houver operações assíncronas pendentes que tenham rotinas de conclusão de E/S e o parâmetro fAlertable for FALSE, essas rotinas de conclusão de E/S não serão executadas mesmo se essas operações de E/S forem concluídas.

Se o parâmetro fAlertable for TRUE e uma das operações pendentes for concluída, o APC será executado e WSAWaitForMultipleEvents retornará WSA_IO_COMPLETION. O evento pendente ainda não está sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente.

Os aplicativos que exigem um estado de espera alertável sem esperar que nenhum objeto de evento seja sinalizado devem usar a função SleepEx do Windows.

A implementação atual do WSAWaitForMultipleEvents chama a função WaitForMultipleObjectsEx .

Nota Tenha cuidado ao chamar o WSAWaitForMultipleEvents com código que cria janelas direta ou indiretamente. Se um thread criar janelas, ele deverá processar mensagens. As transmissões de mensagens são enviadas para todas as janelas do sistema. Um thread que usa WSAWaitForMultipleEvents sem limite de tempo limite (o parâmetro dwTimeout definido como WSA_INFINITE) pode fazer com que o sistema fique em deadlock.
 

Código de exemplo

O exemplo de código a seguir mostra como usar a função WSAWaitForMultipleEvents .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DATA_BUFSIZE 4096

int main()
{
    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData = { 0 };
    int iResult = 0;
    BOOL bResult = TRUE;

    WSABUF DataBuf;
    char buffer[DATA_BUFSIZE];

    DWORD EventTotal = 0;
    DWORD RecvBytes = 0;
    DWORD Flags = 0;
    DWORD BytesTransferred = 0;

    WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
    WSAOVERLAPPED AcceptOverlapped;
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;

    DWORD Index;

    //-----------------------------------------
    // Initialize Winsock
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }
    //-----------------------------------------
    // Create a listening socket bound to a local
    // IP address and the port specified
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error = %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    u_short port = 27015;
    char *ip;
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent *thisHost;

    thisHost = gethostbyname("");
    if (thisHost == NULL) {
        wprintf(L"gethostbyname failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ip = inet_ntoa(*(struct in_addr *) *thisHost->h_addr_list);

    service.sin_addr.s_addr = inet_addr(ip);

    //-----------------------------------------
    // Bind the listening socket to the local IP address
    // and port number
    iResult = bind(ListenSocket, (SOCKADDR *) & service, sizeof (SOCKADDR));
    if (iResult != 0) {
        wprintf(L"bind failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //-----------------------------------------
    // Set the socket to listen for incoming
    // connection requests
    iResult = listen(ListenSocket, 1);
    if (iResult != 0) {
        wprintf(L"listen failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Listening...\n");

    //-----------------------------------------
    // Accept and incoming connection request
    AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Client Accepted...\n");

    //-----------------------------------------
    // Create an event handle and setup an overlapped structure.
    EventArray[EventTotal] = WSACreateEvent();
    if (EventArray[EventTotal] == WSA_INVALID_EVENT) {
        wprintf(L"WSACreateEvent failed with error = %d\n", WSAGetLastError());
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));
    AcceptOverlapped.hEvent = EventArray[EventTotal];

    DataBuf.len = DATA_BUFSIZE;
    DataBuf.buf = buffer;

    EventTotal++;

    //-----------------------------------------
    // Call WSARecv to receive data into DataBuf on 
    // the accepted socket in overlapped I/O mode
    if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) ==
        SOCKET_ERROR) {
        iResult = WSAGetLastError();
        if (iResult != WSA_IO_PENDING)
            wprintf(L"WSARecv failed with error = %d\n", iResult);
    }
    //-----------------------------------------
    // Process overlapped receives on the socket
    while (1) {

        //-----------------------------------------
        // Wait for the overlapped I/O call to complete
        Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);

        //-----------------------------------------
        // Reset the signaled event
        bResult = WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
        if (bResult == FALSE) {
            wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // Determine the status of the overlapped event
        bResult =
            WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE,
                                   &Flags);
        if (bResult == FALSE) {
            wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // If the connection has been closed, close the accepted socket
        if (BytesTransferred == 0) {
            wprintf(L"Closing accept Socket %d\n", AcceptSocket);
            closesocket(ListenSocket);
            closesocket(AcceptSocket);
            WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
            WSACleanup();
            return 1;
        }
        //-----------------------------------------
        // If data has been received, echo the received data
        // from DataBuf back to the client
        iResult =
            WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL);
        if (iResult != 0) {
            wprintf(L"WSASend failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------         
        // Reset the changed flags and overlapped structure
        Flags = 0;
        ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));

        AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

        //-----------------------------------------
        // Reset the data buffer
        DataBuf.len = DATA_BUFSIZE;
        DataBuf.buf = buffer;
    }

    closesocket(ListenSocket);
    closesocket(AcceptSocket);
    WSACleanup();

    return 0;
}


Windows Phone 8: essa função tem suporte para aplicativos da Windows Phone Store no Windows Phone 8 e posterior.

Windows 8.1 e Windows Server 2012 R2: essa função tem suporte para aplicativos da Windows Store em Windows 8.1, Windows Server 2012 R2 e posterior.

Requisitos

   
Cliente mínimo com suporte Windows 8.1, Windows Vista [aplicativos da área de trabalho | Aplicativos UWP]
Servidor mínimo com suporte Windows Server 2003 [aplicativos da área de trabalho | Aplicativos UWP]
Plataforma de Destino Windows
Cabeçalho winsock2.h
Biblioteca Ws2_32.lib
DLL Ws2_32.dll

Confira também

Direitos de acesso padrão

WSACloseEvent

Wsacreateevent

WaitForMultipleObjectsEx

Funções Winsock

Referência de Winsock