views:

506

answers:

1

Hi
Can anyone tell me what I've done wrong with this simple code? When I run it it hangs on

using (Stream postStream = request.EndGetRequestStream(asynchronousResult))

If I comment out the requestState.Wait.WaitOne(); line the code executes correctly but obviously doesn't wait for the response. I'm guessing the the call to EndGetRequestStream is somehow returning me to the context of the main thread?? I'm pretty sure my code is essentially the same as the sample though (MSDN Documentation)

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;

namespace SBRemoteClient
{
    public class JSONClient
    {

        public string ExecuteJSONQuery(string url, string query)
        {
            System.Uri uri = new Uri(url);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";
            request.Accept = "application/json";
            byte[] requestBytes = Encoding.UTF8.GetBytes(query);
            RequestState requestState = new RequestState(request, requestBytes);
            IAsyncResult resultRequest = request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), requestState);
            requestState.Wait.WaitOne();
            IAsyncResult resultResponse = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseStreamCallback), requestState);
            requestState.Wait.WaitOne();

            return requestState.Response;
        }

        private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                RequestState requestState = (RequestState)asynchronousResult.AsyncState;
                HttpWebRequest request = requestState.Request;
                using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
                {
                    postStream.Write(requestState.RequestBytes, 0, requestState.RequestBytes.Length);
                }
                requestState.Wait.Set();
            }
            catch (Exception e) {
                Console.Out.WriteLine(e);
            }
        }

        private static void GetResponseStreamCallback(IAsyncResult asynchronousResult)
        {
            RequestState requestState = (RequestState)asynchronousResult.AsyncState;
            HttpWebRequest request = requestState.Request;
            using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult))
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (StreamReader streamRead = new StreamReader(responseStream))
                    {
                        requestState.Response = streamRead.ReadToEnd();
                        requestState.Wait.Set();
                    }
                }
            }
        }
    }
}
+1  A: 

couple of things:

  1. I don't think you can re-use the same request object. i.e. you can call BeginGetRequestStream once per instance of HttpWebRequest. if you want to perform two requests (calls to the server) you need two instances of HttpWebRequest one per request.

  2. if you want synchronous behavior you have two options: Use the GetRespose method or use begin/end in a synchronous way. to do so you don't need to pass a callback to the BeginGetRequestStream method (you can pass a null instead). take the returned value from BeginGetRequestStream (IAsyncResult) and pass it to the EndGetRequestStream method:

    AsyncResult resultRequest = request.BeginGetRequestStream(null, null);
    Stream postStream = request.EndGetRequestStream(asynchronousResult)
    

EndGetRequestStream will block until the request is completed (this is bad if you are doing it from the UI, but it will still work).

Asher