Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule opisano, że do odbierania i wysyłania komunikatów należy użyć pompy komunikatów.
Oryginalna wersja produktu: Visual C++
Oryginalny numer KB: 303326
Podsumowanie
Począwszy od programu MSXML w wersji 3.0, obiekt żądania XMLHTTP używa Urlmon.dll. Jeśli ustawisz parametr asynchroniczny na VARIANT_TRUE podczas wywoływania open
metody, funkcja URLMON używa mechanizmu kolejki komunikatów do powiadamiania aplikacji, gdy dane staną się dostępne, a readyState
właściwość obiektu żądania XMLHTTP zostanie zmieniona, jak w poniższym przykładzie:
hr=pXMLHTTPReq->open("POST", "http://www.server1.com/test.asp", VARIANT_TRUE);
W aplikacji Visual C++ należy użyć pompy komunikatów do odbierania i wysyłania komunikatów. Jeśli aplikacja nie obsługuje poprawnie przychodzących komunikatów, aplikacja może przestać odpowiadać (zawieszać się), ponieważ readystate
właściwość obiektu żądania XMLHTTP nie zostanie zmieniona.
Uwaga
Ten problem jest specyficzny dla deweloperów języka Visual C++.
Uwaga
Te informacje są specyficzne dla systemu Windows XP. Domyślnie system Windows XP jest dostarczany z MSXML3.0 Service Pack 2 (SP2).
Więcej informacji
W przypadku analizatora MSXML 2.5 dostarczanego z systemem Microsoft Windows 2000 nie jest wymagana żadna taka pompa komunikatów. W systemie Windows XP program MSXML 3.0 z dodatkiem SP2 jest zainstalowany w trybie zastępowania, więc może wystąpić ten problem.
Poniżej przedstawiono przykładową implementację pompy komunikatów z obiektem żądania XMLHTTP. Aby go przetestować, wklej kod do pliku .cpp, a następnie skompiluj i uruchom plik jako projekt aplikacji konsolowej Win32.
#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;
}
Uwaga
Przetwarzanie asynchroniczne w praktyce jest bardziej skomplikowane. Przed próbą użycia trybu asynchronicznego należy przetestować aplikację w trybie synchronicznym.
W przypadku korzystania z SeverXMLHTTPRequest
obiektu należy uruchomić narzędzie Proxycfg, aby ustawić informacje o serwerze proxy. Aby uzyskać więcej informacji, zobacz Często zadawane pytania dotyczące serverXMLHTTP.
ServerXMLHTTP nie używa Urlmon.dll. Jeśli jednak używasz ServerXMLHTTP w trybie asynchronicznym, potrzebna jest również ta pompa komunikatów, ponieważ analizator wywołuje zdarzenie, wysyłając komunikaty z powrotem do wątku.
ServerXMLHTTP zawiera również metodę o nazwie waitForResponse
, która nie jest dostępna w przypadku protokołu XMLHTTP.
waitForResponse
czeka, gdy żądanie asynchroniczne jest przetwarzane. Metoda waitForResponse
automatycznie pompuje komunikaty okna, więc kod aplikacji klienta nie musi tego robić. Dzięki temu kod aplikacji może zostać uproszczony w następujący sposób:
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();