Search code examples
windows-8microsoft-metrowindows-runtimewinrt-async

How can I guarantee that IXMLHTTPRequest2 callbacks will be called on a different thread?


I am using the IXMLHTTPRequest2/IXMLHTTPRequest2Callback interface to send an HTTP request and to process the response. Sometimes the response callbacks (OnHeadersAvailable(), etc.) are called on a thread that is different from the thread that sent the request, and sometimes the callbacks are called on the same thread that sent the request, as shown in the call stack below:

my.dll!xxxXMLHTTPRequest2Callback::OnHeadersAvailable(IXMLHTTPRequest2 * pXHR, unsigned long dwStatus, const wchar_t * pwszStatus) Line 185 C++
msxml6.dll!URLMONRequest::_CallOnHeadersAvailable() Line 305    C++
msxml6.dll!URLMONRequest::_OnResponse(unsigned long dwResponseCode, const wchar_t * pwszResponseHeaders, const wchar_t * pwszRequestHeaders) Line 2946  C++
msxml6.dll!URLMONRequest::OnResponse(unsigned long dwResponseCode, const wchar_t * pwszResponseHeaders, const wchar_t * pwszRequestHeaders, wchar_t * * ppwszAdditionalRequestHeaders) Line 2993    C++
msxml6.dll!URLMONRequest::URLMONRequestSink::OnResponse(unsigned long dwResponseCode, const wchar_t * szResponseHeaders, const wchar_t * szRequestHeaders, wchar_t * * pszAdditionalRequestHeaders) Line 212    C++
urlmon.dll!CINetHttp::QueryStatusOnResponseDefault()    Unknown
urlmon.dll!CINetHttp::QueryStatusOnResponse()   Unknown
urlmon.dll!CINetHttp::INetAsyncSendRequest()    Unknown
urlmon.dll!CINetHttp::INetAsyncOpenRequest()    Unknown
urlmon.dll!CINet::INetAsyncConnect()    Unknown
urlmon.dll!CINet::INetAsyncOpen()   Unknown
urlmon.dll!CINet::StartCommon() Unknown
urlmon.dll!CINet::Start()   Unknown
msxml6.dll!URLMONRequest::send(tagVARIANT varBody) Line 838 C++
msxml6.dll!XMLHttp::send(tagVARIANT varBody) Line 549   C++
msxml6.dll!XMLHttp2::_Send(ISequentialStream * pBody, unsigned __int64 cbBody) Line 2440    C++
msxml6.dll!XMLHttp2::Send(ISequentialStream * pBody, unsigned __int64 cbBody) Line 2993 C++

I expected the callbacks to always be called on a different thread, since this is documented as an asynchronous interface. Is there a way that I can guarantee that the callbacks always will be called on a thread that is different from the thread that sends the request? Thank you for any information.


Solution

  • "Asynchronous" simply means that it will not consume a thread from the thread pool until a result is available to process.

    Short of writing your own pool manager, you cannot control how results of asynchronous requests are allocated to a given thread.

    You can have the thread receiving the async callback queue the result (e.g. use a BlockingCollection) and have a thread of your choice pull work items off of the queue. That way you can control which thread processes the result, even if you cannot control which thread receives the result.