private async void StartRequest(object obj) { WinHttpRequestState state = (WinHttpRequestState)obj; bool secureConnection = false; HttpResponseMessage responseMessage = null; Exception savedException = null; SafeWinHttpHandle connectHandle = null; if (state.CancellationToken.IsCancellationRequested) { state.Tcs.TrySetCanceled(state.CancellationToken); return; } try { EnsureSessionHandleExists(state); SetSessionHandleOptions(); // Specify an HTTP server. connectHandle = Interop.WinHttp.WinHttpConnect( _sessionHandle, state.RequestMessage.RequestUri.Host, (ushort)state.RequestMessage.RequestUri.Port, 0); ThrowOnInvalidHandle(connectHandle); connectHandle.SetParentHandle(_sessionHandle); if (state.RequestMessage.RequestUri.Scheme == UriScheme.Https) { secureConnection = true; } else { secureConnection = false; } // Create an HTTP request handle. state.RequestHandle = Interop.WinHttp.WinHttpOpenRequest( connectHandle, state.RequestMessage.Method.Method, state.RequestMessage.RequestUri.PathAndQuery, null, Interop.WinHttp.WINHTTP_NO_REFERER, Interop.WinHttp.WINHTTP_DEFAULT_ACCEPT_TYPES, secureConnection ? Interop.WinHttp.WINHTTP_FLAG_SECURE : 0); ThrowOnInvalidHandle(state.RequestHandle); state.RequestHandle.SetParentHandle(connectHandle); // Set callback function. SetStatusCallback(state.RequestHandle, WinHttpRequestCallback.StaticCallbackDelegate); // Set needed options on the request handle. SetRequestHandleOptions(state); bool chunkedModeForSend = IsChunkedModeForSend(state.RequestMessage); AddRequestHeaders( state.RequestHandle, state.RequestMessage, _cookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer ? _cookieContainer : null); uint proxyAuthScheme = 0; uint serverAuthScheme = 0; state.RetryRequest = false; // The only way to abort pending async operations in WinHTTP is to close the WinHTTP handle. // We will detect a cancellation request on the cancellation token by registering a callback. // If the callback is invoked, then we begin the abort process by disposing the handle. This // will have the side-effect of WinHTTP cancelling any pending I/O and accelerating its callbacks // on the handle and thus releasing the awaiting tasks in the loop below. This helps to provide // a more timely, cooperative, cancellation pattern. using (state.CancellationToken.Register(s => ((WinHttpRequestState)s).RequestHandle.Dispose(), state)) { do { _authHelper.PreAuthenticateRequest(state, proxyAuthScheme); await InternalSendRequestAsync(state).ConfigureAwait(false); if (state.RequestMessage.Content != null) { await InternalSendRequestBodyAsync(state, chunkedModeForSend).ConfigureAwait(false); } bool receivedResponse = await InternalReceiveResponseHeadersAsync(state).ConfigureAwait(false); if (receivedResponse) { _authHelper.CheckResponseForAuthentication( state, ref proxyAuthScheme, ref serverAuthScheme); } } while (state.RetryRequest); } state.CancellationToken.ThrowIfCancellationRequested(); responseMessage = WinHttpResponseParser.CreateResponseMessage(state, _doManualDecompressionCheck); // Since the headers have been read, set the "receive" timeout to be based on each read // call of the response body data. WINHTTP_OPTION_RECEIVE_TIMEOUT sets a timeout on each // lower layer winsock read. uint optionData = (uint)_receiveDataTimeout.TotalMilliseconds; SetWinHttpOption(state.RequestHandle, Interop.WinHttp.WINHTTP_OPTION_RECEIVE_TIMEOUT, ref optionData); } catch (Exception ex) { if (state.SavedException != null) { savedException = state.SavedException; } else { savedException = ex; } } finally { SafeWinHttpHandle.DisposeAndClearHandle(ref connectHandle); } // Move the main task to a terminal state. This releases any callers of SendAsync() that are awaiting. if (responseMessage != null) { state.Tcs.TrySetResult(responseMessage); } else { HandleAsyncException(state, savedException); } }