Freigeben über


Eine Visual C++-Anwendung, die ServerXMLHTTP oder XMLHTTP im asynchronen Modus verwendet, muss Nachrichten bearbeiten.

In diesem Artikel wird beschrieben, dass Sie eine Nachrichtenpumpe verwenden müssen, um Nachrichten zu empfangen und zu versenden.

Originalproduktversion: Visual C++
Ursprüngliche KB-Nummer: 303326

Übersicht

Ab MSXML Version 3.0 verwendet das XMLHTTP-Anforderungsobjekt Urlmon.dll. Wenn Sie den asynchronen Parameter beim Aufrufen der Methode auf VARIANT_TRUE festlegen, verwendet URLMON den Mechanismus für die open Nachrichtenwarteschlange, um die Anwendung zu benachrichtigen, wenn Daten verfügbar werden, und die readyState Eigenschaft des XMLHTTP-Anforderungsobjekts wird geändert, wie im folgenden Beispiel gezeigt:

hr=pXMLHTTPReq->open("POST", "http://www.server1.com/test.asp", VARIANT_TRUE);

In einer Visual C++-Anwendung müssen Sie eine Nachrichtenpumpe verwenden, um Nachrichten zu empfangen und zu verteilen. Wenn die Anwendung die eingehenden Nachrichten nicht ordnungsgemäß verarbeitet, reagiert die Anwendung möglicherweise nicht mehr (hängend), da die readystate Eigenschaft des XMLHTTP-Anforderungsobjekts nicht geändert wird.

Notiz

Dieses Problem ist für Visual C++-Entwickler spezifisch.

Notiz

Diese Informationen sind für Windows XP spezifisch. Standardmäßig wird Windows XP mit MSXML3.0 Service Pack 2 (SP2) ausgeliefert.

Weitere Informationen

Mit dem MSXML 2.5-Parser, der im Lieferumfang von Microsoft Windows 2000 enthalten ist, ist keine solche Meldungspumpe erforderlich. Mit Windows XP ist MSXML 3.0 SP2 im Ersetzungsmodus installiert, sodass dieses Problem auftreten kann.

Nachfolgend sehen Sie eine Beispielimplementierung der Nachrichtenpumpe mit dem XMLHTTP-Anforderungsobjekt. Zum Testen fügen Sie den Code in eine .cpp Datei ein, kompilieren und führen sie dann als Win32-Konsolenanwendungsprojekt aus.

#import "msxml3.dll"
using namespace MSXML2; // For Msxml3.dll.

#include "stdio.h"

void dump_com_error(_com_error &e)
{
    printf("Error\n");
    printf("\a\tCode = %08lx\n", e.Error());
    printf("\a\tCode meaning = %s", e.ErrorMessage());
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());
    printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
    printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}

int main()
{
    HRESULT hr = CoInitialize(NULL);

    try{
        IXMLHTTPRequestPtr pXMLHTTPReq = NULL;
        hr=pXMLHTTPReq.CreateInstance(__uuidof(XMLHTTP30));

        //Uncomment the following lines if you are using ServerXMLHTTPRequest.
        //IServerXMLHTTPRequestPtr pXMLHTTPReq = NULL;
        //hr=pXMLHTTPReq.CreateInstance(__uuidof(ServerXMLHTTP30));

        hr=pXMLHTTPReq->open("POST", "http://www.server1.com/test1.asp", VARIANT_TRUE);

        hr = pXMLHTTPReq->setRequestHeader("charset", "UTF-8");
        hr=pXMLHTTPReq->send("<?xml version=\"1.0\" encoding=\"UTF-8\"?><REQUEST>request1</REQUEST>");

        long readyState = READYSTATE_UNINITIALIZED;
        MSG msg;
        while (readyState != READYSTATE_COMPLETE)
        {
            //Without this message pump, readyState does not change.
            if (PeekMessage(&msg, 0, 0 ,0, PM_REMOVE))
            {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }

            readyState = pXMLHTTPReq->GetreadyState();

        }
        MessageBox(NULL, "readyState is COMPLETE ", "readystate", MB_OK);

        long status= pXMLHTTPReq->Getstatus();
    }
    catch(_com_error &e)
    {
        dump_com_error(e);
    }
    return 0;
}

Notiz

Die asynchrone Verarbeitung in der Praxis ist komplizierter. Sie sollten Ihre Anwendung im synchronen Modus testen, bevor Sie versuchen, asynchronen Modus zu verwenden.

Wenn Sie das SeverXMLHTTPRequest Objekt verwenden, müssen Sie das Proxycfg-Hilfsprogramm ausführen, um die Proxyinformationen festzulegen. Weitere Informationen finden Sie unter Häufig gestellte Fragen zu ServerXMLHTTP.

ServerXMLHTTP verwendet keine Urlmon.dll. Wenn Sie ServerXMLHTTP jedoch im asynchronen Modus verwenden, benötigen Sie diese Meldungspumpe auch, da der Parser das Ereignis auslöst, indem Nachrichten zurück in den Thread gepostet werden.

ServerXMLHTTP enthält auch eine Methode namens waitForResponse, die mit XMLHTTP nicht verfügbar ist. waitForResponse wartet, während eine asynchrone Anforderung verarbeitet wird. Die waitForResponse Methode pumpt Fensternachrichten automatisch, sodass der Anwendungscode des Clients dies nicht tun muss. Dadurch kann der Anwendungscode wie folgt vereinfacht werden:

hr=pXMLHTTPReq.CreateInstance(__uuidof(ServerXMLHTTP30));

hr=pXMLHTTPReq->open("POST", "http://www.server1.com/test1.asp", VARIANT_TRUE);

hr = pXMLHTTPReq->setRequestHeader("charset", "UTF-8");
hr=pXMLHTTPReq->send("<?xml version=\"1.0\" encoding=\"UTF-8\"?><REQUEST>request1</REQUEST>");

VARIANT Timeout;
VariantInit(&Timeout);
Timeout.vt = VT_I4;
Timeout.lVal = 60; // Timeout value of 60 seconds.

VARIANT_BOOL bSucceeded;
//Passing vtMissing as the first parameter sets the timeout value to infinite.
hr = pXMLHTTPReq->waitForResponse(Timeout, &bSucceeded);

long status= pXMLHTTPReq->Getstatus();