Condividi tramite


Funzione WSAWaitForMultipleEvents (winsock2.h)

La funzione WSAWaitForMultipleEvents restituisce quando uno o tutti gli oggetti evento specificati si trovano nello stato segnalato, quando l'intervallo di timeout scade o quando viene eseguita una routine di completamento di I/O.

Sintassi

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

Parametri

[in] cEvents

Numero di handle di oggetti evento nella matrice a cui punta lphEvents. Il numero massimo di handle di oggetti evento è WSA_MAXIMUM_WAIT_EVENTS. È necessario specificare uno o più eventi.

[in] lphEvents

Puntatore a una matrice di handle di oggetti evento. La matrice può contenere handle di oggetti di tipi diversi. Potrebbe non contenere più copie dello stesso handle se il parametro fWaitAll è impostato su TRUE. Se uno di questi handle viene chiuso mentre l'attesa è ancora in sospeso, il comportamento di WSAWaitForMultipleEvents non è definito.

Gli handle devono avere il diritto di accesso SYNC . Per altre informazioni, vedere Diritti di accesso standard.

[in] fWaitAll

Valore che specifica il tipo di attesa. Se TRUE, la funzione restituisce quando viene segnalato lo stato di tutti gli oggetti nella matrice lphEvents . Se FALSE, la funzione restituisce quando viene segnalato uno degli oggetti evento. In quest'ultimo caso, il valore restituito meno WSA_WAIT_EVENT_0 indica l'indice dell'oggetto evento il cui stato ha causato la restituzione della funzione. Se durante la chiamata viene segnalato più di un oggetto evento, questo è l'indice della matrice all'oggetto evento segnalato con il valore di indice più piccolo di tutti gli oggetti evento segnalati.

[in] dwTimeout

Intervallo di timeout, in millisecondi. WSAWaitForMultipleEvents restituisce se l'intervallo di timeout scade, anche se le condizioni specificate dal parametro fWaitAll non sono soddisfatte. Se il parametro dwTimeout è zero, WSAWaitForMultipleEvents verifica lo stato degli oggetti evento specificati e restituisce immediatamente. Se dwTimeout è WSA_INFINITE, WSAWaitForMultipleEvents attende per sempre; ovvero, l'intervallo di timeout non scade mai.

[in] fAlertable

Valore che specifica se il thread viene inserito in uno stato di attesa avvisabile in modo che il sistema possa eseguire routine di completamento di I/O. Se TRUE, il thread viene inserito in uno stato di attesa avvisabile e WSAWaitForMultipleEvents può restituire quando il sistema esegue una routine di completamento di I/O. In questo caso, WSA_WAIT_IO_COMPLETION viene restituito e l'evento in attesa non viene ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents . Se FALSE, il thread non viene inserito in uno stato di attesa avvisabile e le routine di completamento di I/O non vengono eseguite.

Valore restituito

Se la funzione WSAWaitForMultipleEvents ha esito positivo, il valore restituito al termine dell'operazione è uno dei valori seguenti.

Valore restituito Significato
WSA_WAIT_EVENT_0 a (WSA_WAIT_EVENT_0 + cEvents - 1)
Se il parametro fWaitAll è TRUE, il valore restituito indica che tutti gli oggetti evento specificati vengono segnalati.

Se il parametro fWaitAll è FALSE, il valore restituito meno WSA_WAIT_EVENT_0 indica l'indice della matrice lphEvents dell'oggetto evento segnalato che ha soddisfatto l'attesa. Se durante la chiamata viene segnalato più di un oggetto evento, il valore restituito indica l'indice della matrice lphEvents dell'oggetto evento segnalato con il valore di indice più piccolo di tutti gli oggetti evento segnalati.

WSA_WAIT_IO_COMPLETION
L'attesa è stata terminata da una o più routine di completamento di I/O eseguite. L'evento in attesa non è ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents . Questo valore restituito può essere restituito solo se il parametro fAlertable è TRUE.
WSA_WAIT_TIMEOUT
L'intervallo di timeout trascorso e le condizioni specificate dal parametro fWaitAll non sono state soddisfatte. Non sono state eseguite routine di completamento di I/O.
 

Se la funzione WSAWaitForMultipleEvents ha esito negativo, il valore restituito è WSA_WAIT_FAILED. La tabella seguente elenca i valori che possono essere usati con WSAGetLastError per ottenere informazioni di errore estese.

Codice di errore Significato
WSANOTINITIALISED Prima di usare questa funzione, è necessario eseguire una chiamata WSAStartup riuscita.
WSAENETDOWN Il sottosistema di rete non è riuscito.
WSAEINPROGRESS Una chiamata windows Sockets 1.1 bloccata è in corso oppure il provider di servizi sta ancora elaborando una funzione di callback.
WSA_NOT_ENOUGH_MEMORY Memoria insufficiente disponibile per completare l'operazione.
WSA_INVALID_HANDLE Uno o più valori della matrice lphEvents non è un handle dell'oggetto evento valido.
WSA_INVALID_PARAMETER Il parametro cEvents non contiene un conteggio di handle valido.

Commenti

La funzione WSAWaitForMultipleEvents determina se sono stati soddisfatti i criteri di attesa. Se i criteri non sono stati soddisfatti, il thread chiamante entra nello stato di attesa. Non usa tempo di processore in attesa dei criteri da soddisfare.

La funzione WSAWaitForMultipleEvents restituisce quando uno o tutti gli oggetti specificati si trovano nello stato segnalato o quando l'intervallo di timeout viene trascorso.

Quando il parametro bWaitAll è TRUE, l'operazione di attesa viene completata solo quando gli stati di tutti gli oggetti sono stati impostati su segnalato. La funzione non modifica gli stati degli oggetti specificati fino a quando gli stati di tutti gli oggetti sono stati impostati per segnalare.

Quando il parametro bWaitAll è FALSE, WSAWaitForMultipleEvents controlla gli handle nella matrice lphEvents in ordine a partire dall'indice 0, fino a quando non viene segnalato uno degli oggetti. Se più oggetti vengono segnalati, la funzione restituisce l'indice del primo handle nella matrice lphEvents l cui oggetto è stato segnalato.

Questa funzione viene usata anche per eseguire un'attesa avvisabile impostando il parametro fAlertable su TRUE. Ciò consente alla funzione di restituire quando il sistema esegue una routine di completamento di I/O tramite il thread chiamante.

Un thread deve trovarsi in uno stato di attesa avvisabile per consentire al sistema di eseguire routine di completamento di I/O (chiamate di routine asincrone o API). Quindi, se un'applicazione chiama WSAWaitForMultipleEvents quando sono presenti operazioni asincrone in sospeso con routine di completamento di I/O e il parametro fAlertable è FALSE, tali routine di completamento di I/O non verranno eseguite anche se tali operazioni di I/O vengono completate.

Se il parametro fAlertable è TRUE e una delle operazioni in sospeso viene completata, l'APC viene eseguito e WSAWaitForMultipleEvents restituirà WSA_IO_COMPLETION. L'evento in sospeso non viene ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents .

Le applicazioni che richiedono uno stato di attesa avvisabile senza attendere che tutti gli oggetti evento vengano segnalati devono usare la funzione Windows SleepEx .

L'implementazione corrente di WSAWaitForMultipleEvents chiama la funzione WaitForMultipleObjectsEx .

Nota Prestare attenzione quando si chiama WSAWaitForMultipleEvents con codice che crea direttamente o indirettamente finestre. Se un thread crea finestre, deve elaborare i messaggi. Le trasmissioni dei messaggi vengono inviate a tutte le finestre del sistema. Un thread che usa WSAWaitForMultipleEvents senza limite di timeout (il parametro dwTimeout impostato su WSA_INFINITE) può causare il deadlock del sistema.
 

Codice di esempio

Nell'esempio di codice seguente viene illustrato come usare la funzione 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: questa funzione è supportata per le app Windows Phone Store in Windows Phone 8 e versioni successive.

Windows 8.1 e Windows Server 2012 R2: questa funzione è supportata per le app di Windows Store in Windows 8.1, Windows Server 2012 R2 e versioni successive.

Requisiti

   
Client minimo supportato Windows 8.1, Windows Vista [app desktop | App UWP]
Server minimo supportato Windows Server 2003 [app desktop | App UWP]
Piattaforma di destinazione Windows
Intestazione winsock2.h
Libreria Ws2_32.lib
DLL Ws2_32.dll

Vedi anche

Diritti di accesso standard

WSACloseEvent

WSACreateEvent

WaitForMultipleObjectsEx

Funzioni Winsock

Informazioni di riferimento su Winsock