Condividi tramite


Metodo IHttpServer::AssociateWithThreadPool

Associa un'operazione di completamento asincrona al pool di thread.

Sintassi

virtual HRESULT AssociateWithThreadPool(  
   IN HANDLE hHandle,  
   IN LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine  
) = 0;  

Parametri

hHandle
[IN] Oggetto HANDLE per l'operazione asincrona.

completionRoutine
[IN] Puntatore LPOVERLAPPED_COMPLETION_ROUTINE alla funzione.

Valore restituito

Oggetto HRESULT. I valori possibili includono, ma non sono limitati a, quelli indicati nella tabella seguente.

Valore Descrizione
S_OK Indica che l'operazione ha avuto esito positivo.

Commenti

Gli sviluppatori possono usare il AssociateWithThreadPool metodo per associare un handle per un'operazione di input/output asincrona al pool di thread IIS. Poiché l'operazione asincrona associata a tale handle verrà completata all'interno del pool di thread IIS, il AssociateWithThreadPool metodo consente di eseguire una serie di operazioni asincrone senza mantenere il proprio pool di thread.

Esempio

Nell'esempio di codice seguente viene illustrato come usare il AssociateWithThreadPool metodo per creare un modulo HTTP che crea una condizione che richiede un'operazione di input/output asincrona e associa la routine di completamento asincrona al pool di thread IIS.

#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <httpserv.h>

// Create a pointer for the global server interface.
IHttpServer * g_pGlobalInfo = NULL;

// Create a global file handle.
HANDLE g_hFile = NULL;

// Create a utility method for asynchronous completion.
VOID
__stdcall
MyCompletionRoutine(
    DWORD dwErrorCode,
    DWORD dwNumberOfBytesTransfered,
    LPOVERLAPPED lpOverlapped)
{
    if ((g_hFile != NULL) && (g_hFile != INVALID_HANDLE_VALUE))
    {
        CloseHandle(g_hFile);
    }    
    return;
}

// Create the module class.
class MyHttpModule : public CHttpModule
{

public:
    REQUEST_NOTIFICATION_STATUS
    OnSendResponse(
        IN IHttpContext * pHttpContext,
        IN ISendResponseProvider * pProvider
    )
    {
        UNREFERENCED_PARAMETER( pHttpContext );
        UNREFERENCED_PARAMETER( pProvider );

        BOOL fAuthenticated = FALSE;

        // Retrieve an IHttpUser interface.
        IHttpUser * pHttpUser = pHttpContext->GetUser();
        char * pszUserName = NULL;
        PCWSTR pwszUserName = NULL;

        // Test for an error.
        if (pHttpUser != NULL)
        {
            // Retrieve the user name.
            pwszUserName = pHttpUser->GetUserName();
            // Test for an error.
            if (pwszUserName!=NULL)
            {
                // Test for anonymous user.
                if (wcslen(pwszUserName)>0)
                {
                    // Set the flag to indicate an authenticated user.
                    fAuthenticated = TRUE;
                }
            }
        }

        // Test for an authenticated user.
        if (fAuthenticated == FALSE)
        {
            // Clear the existing response.
            pHttpContext->GetResponse()->Clear();
            // Return an access denied message.
            pHttpContext->GetResponse()->SetStatus(401,"Access denied.",0,0);
            // End additional processing.
            return RQ_NOTIFICATION_FINISH_REQUEST;
        }

        g_hFile = CreateFile(TEXT("d:\\inetpub\\wwwroot\\myfile.txt"),
            GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
        
        if (g_hFile == INVALID_HANDLE_VALUE) 
        { 
            char szBuffer[256] = "";
            sprintf_s(szBuffer,256,"Could not open file (error %d)\n", GetLastError());
            WriteResponseMessage(pHttpContext,szBuffer);
            return RQ_NOTIFICATION_FINISH_REQUEST;
        }
        else
        {
            OVERLAPPED oOverlapped;
            oOverlapped.hEvent = NULL;
            oOverlapped.Offset = 0;
            oOverlapped.OffsetHigh = 0;
            DWORD dwBytesWritten = 0;
            g_pGlobalInfo->AssociateWithThreadPool(g_hFile,&MyCompletionRoutine);
            //pszUserName = (char*) pHttpContext->AllocateRequestMemory( (DWORD) wcslen(pwszUserName)+1 );
            //wcstombs(pszUserName,pwszUserName,wcslen(pwszUserName));
            //WriteFile(g_hFile, pszUserName, strlen(pszUserName), &dwBytesWritten, &oOverlapped);
            WriteFile(g_hFile, "Hello", strlen("Hello"), &dwBytesWritten, oOverlapped);
            return RQ_NOTIFICATION_PENDING;
        }
    }

private:

    // Create a utility method that inserts a string value into the response.
    HRESULT WriteResponseMessage(
        IHttpContext * pHttpContext,
        PCSTR pszBuffer
    )
    {
        // Create an HRESULT to receive return values from methods.
        HRESULT hr;
        
        // Create a data chunk. (Defined in the Http.h file.)
        HTTP_DATA_CHUNK dataChunk;
        // Set the chunk to a chunk in memory.
        dataChunk.DataChunkType = HttpDataChunkFromMemory;
        // Buffer for bytes written of data chunk.
        DWORD cbSent;

        // Set the chunk to the buffer.
        dataChunk.FromMemory.pBuffer =
            (PVOID) pszBuffer;
        // Set the chunk size to the buffer size.
        dataChunk.FromMemory.BufferLength =
            (USHORT) strlen(pszBuffer);
        // Insert the data chunk into the response.
        hr = pHttpContext->GetResponse()->WriteEntityChunks(
            &dataChunk,1,FALSE,TRUE,&cbSent);
        // Test for an error.
        if (FAILED(hr))
        {
            // Return the error status.
            return hr;
        }

        // Return a success status.
        return S_OK;
    }
};

// Create the module's class factory.
class MyHttpModuleFactory : public IHttpModuleFactory
{
public:
    HRESULT
    GetHttpModule(
        OUT CHttpModule ** ppModule, 
        IN IModuleAllocator * pAllocator
    )
    {
        UNREFERENCED_PARAMETER( pAllocator );

        // Create a new instance.
        MyHttpModule * pModule = new MyHttpModule;

        // Test for an error.
        if (!pModule)
        {
            // Return an error if the factory cannot create the instance.
            return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
        }
        else
        {
            // Return a pointer to the module.
            *ppModule = pModule;
            pModule = NULL;
            // Return a success status.
            return S_OK;
        }            
    }

    void Terminate()
    {
        // Remove the class from memory.
        delete this;
    }
};

// Create the module's exported registration function.
HRESULT
__stdcall
RegisterModule(
    DWORD dwServerVersion,
    IHttpModuleRegistrationInfo * pModuleInfo,
    IHttpServer * pGlobalInfo
)
{
    UNREFERENCED_PARAMETER( dwServerVersion );
    UNREFERENCED_PARAMETER( pGlobalInfo );

    // Store the pointer for the global server interface.
    g_pGlobalInfo = pGlobalInfo;

    // Set the request notifications and exit.
    return pModuleInfo->SetRequestNotifications(
        new MyHttpModuleFactory,
        RQ_SEND_RESPONSE,
        0
    );
}

Il modulo deve esportare la funzione RegisterModule . È possibile esportare questa funzione creando un file di definizione del modulo (con estensione def) per il progetto oppure è possibile compilare il modulo usando l'opzione /EXPORT:RegisterModule . Per altre informazioni, vedere Procedura dettagliata: Creazione di un modulo HTTP Request-Level tramite codice nativo.

Facoltativamente, è possibile compilare il codice usando la __stdcall (/Gz) convenzione chiamante anziché dichiarare esplicitamente la convenzione chiamante per ogni funzione.

Requisiti

Tipo Descrizione
Client - IIS 7.0 in Windows Vista
- IIS 7.5 in Windows 7
- IIS 8.0 in Windows 8
- IIS 10.0 in Windows 10
Server - IIS 7.0 in Windows Server 2008
- IIS 7.5 in Windows Server 2008 R2
- IIS 8.0 in Windows Server 2012
- IIS 8.5 in Windows Server 2012 R2
- IIS 10.0 in Windows Server 2016
Prodotto - IIS 7.0, IIS 7.5, IIS 8.0, IIS 8.5, IIS 10.0
- IIS Express 7,5, IIS Express 8.0, IIS Express 10.0
Intestazione Httpserv.h

Vedere anche

Interfaccia IHttpServer