private static void GetResponseAsync(HttpWebRequest request, string method, ref BackgroundWorker bw, ref DoWorkEventArgs e, out string pointer, out string error) { const string SOURCE = CLASS_NAME + "GetResponseAsync"; pointer = ""; error = ""; try { //make async call to get response //then we can abort if Cancel is called on the background worker var state = new RequestState { Request = request, Method = method }; _callbackDone = new ManualResetEvent(false); IAsyncResult ar = request.BeginGetResponse( ResponseCallback, state); //poll every 250 ms const int WAIT = 250; int cycles = 0; ar.AsyncWaitHandle.WaitOne(WAIT, true); while (ar.IsCompleted != true) { cycles += 1; //check for manual/application Cancel if (bw.CancellationPending) { request.Abort(); e.Cancel = true; Logger.Info(SOURCE, string.Format( "aborting request for {0} in response to CancellationPending flag", method)); return; } if (cycles >= 120) { //enforce timeout of 30 seconds (120 * 250ms) request.Abort(); Logger.Info(SOURCE, string.Format( "request for {0} timed out after {1} sec", method, (cycles * WAIT / 1000))); error = "request timed out"; return; } //wait for another 250 ms ar.AsyncWaitHandle.WaitOne(WAIT, true); } _callbackDone.WaitOne(); _callbackDone.Close(); _callbackDone = null; using (var response = state.Response) { if (response != null) { //read the response stream var stream = response.GetResponseStream(); if (stream != null) { using (var reader = new StreamReader(stream)) { var responseText = reader.ReadToEnd(); Logger.Verbose(SOURCE, string.Format("response for {0} = {1}", method, responseText)); switch (method) { case "UpdateContent": error = ParseUpdateResponse(responseText); break; case "ReceiveSegment": error = ParseSegmentResponse(responseText); break; default: ParsePostResponse(responseText, ref pointer, out error); break; } } } } else { //treat this as an error Logger.Warning(SOURCE, string.Format( "no response for {0}", method)); error = "No response"; } } } catch (WebException wex) { //exception will be raised if the server didn't return 200 - OK //try to retrieve more information about the network error if (wex.Response != null) { try { var errResponse = (HttpWebResponse)wex.Response; error = string.Format("code:{0}; desc:{1}", errResponse.StatusCode, errResponse.StatusDescription); } catch (Exception ex) { Logger.Error(SOURCE, ex.ToString()); } } else { error = wex.ToString(); } } catch (Exception ex) { error = ex.ToString(); Logger.Error(SOURCE, ex.ToString()); } }
private static HttpWebRequest CreateRequestAsync(string server, string port, byte[] postData, ref BackgroundWorker bw, ref DoWorkEventArgs e) { const string SOURCE = CLASS_NAME + "CreateRequestAsync"; HttpWebRequest request = null; try { if (!server.Contains("://")) server = "https://" + server; var route = Properties.Settings.Default.Route; if (route != "DynamicContentServer/ContentServer") { Logger.Verbose(SOURCE,"submitting request to " + route); } var uri = new Uri(string.Format("{0}:{1}/{2}", server, port, route)); request = WebRequest.Create(uri) as HttpWebRequest; if (request == null) return null; request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postData.Length; request.AllowWriteStreamBuffering = false; var state = new RequestState { Request = request, Data = postData }; //request.KeepAlive; //request.Proxy; request.UserAgent = "outlook"; //use manual reset event to signal when callback is complete _callbackDone = new ManualResetEvent(false); //initiate callback for the request stream var ar = request.BeginGetRequestStream( RequestStreamCallback, state); //this will signal when the callback fires, but before the data gets written to the stream //poll every 50 ms var cycles = 0; const int WAIT = 50; ar.AsyncWaitHandle.WaitOne(WAIT, true); while (ar.IsCompleted != true) { cycles++; if (bw.CancellationPending) { request.Abort(); e.Cancel = true; Logger.Info(SOURCE, "aborting call for RequestStream in response to CancellationPending flag"); break; } if (cycles >= 600) { //enforce timeout of 30 seconds (600 * 50ms) request.Abort(); Logger.Info(SOURCE, string.Format( "aborting call for RequestStream after {0} sec timeout", cycles * WAIT / 1000)); break; } //wait for another 50 ms ar.AsyncWaitHandle.WaitOne(WAIT, true); } //wait for the callback to signal completion _callbackDone.WaitOne(); _callbackDone.Close(); _callbackDone = null; } catch (Exception ex) { Logger.Error(SOURCE, string.Format( "WebRequest.Create failed using '{0}:{1}', ContentLength {2}: {3}", server, port, postData.Length, ex.Message)); } return request; }