Search code examples
c#windows-phone-7httpwebrequestmultithreadingmanualresetevent

Why isn't the BeginGetResponse callback being called?


Here's my code:

namespace RequestApi
{
    public partial class MainPage : PhoneApplicationPage
    {
        private BackgroundWorker bw;
        private string ans;
        private JObject ansJson;
        private static ManualResetEvent allDone = new ManualResetEvent(false);
        // Constructor
        public MainPage()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            string url = "http://192.168.0.43:8182/Account/SignIn";
            CreateRequest(url);

            userId.Text = ansJson.Value<int>("user_id").ToString();

        }


        private void CreateRequest(string url)
        {
            Debug.WriteLine("CreateRequest");
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.ContentType = "application/json";
            req.Method = "POST";
            req.BeginGetRequestStream(new AsyncCallback(RequestCallback), req);
            allDone.WaitOne();
        }

        private  void RequestCallback(IAsyncResult aresult)
        {
            Debug.WriteLine("RequestCallback");
            HttpWebRequest req = (HttpWebRequest)aresult.AsyncState;
            Stream postStream = req.EndGetRequestStream(aresult);

            string obj = "{ 'username': 'test_2@aragast.com', 'password': 'a123456' }";
            JObject json = JObject.Parse(obj);
            string s = JsonConvert.SerializeObject(json);
            byte[] postdata = System.Text.Encoding.Unicode.GetBytes(s);

            postStream.Write(postdata, 0, postdata.Length);
            postStream.Close();

            req.BeginGetResponse(new AsyncCallback(ResponseCallback), req);


        }

        private  void ResponseCallback(IAsyncResult aresult)
        {
            Debug.WriteLine("ResponseCallback");
            HttpWebRequest req = (HttpWebRequest)aresult.AsyncState;
            HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(aresult);
            StreamReader reader = new StreamReader(resp.GetResponseStream());
            string response = reader.ReadToEnd();
            Debug.WriteLine(response);
            JObject responseJson = JObject.Parse(response);
            ansJson = responseJson;
            Debug.WriteLine("ansJson from responseCallback {0}", ansJson);
            reader.Close();
            resp.Close();
            allDone.Set();

        }
    }
}

When I debug application it entered CreateRequest then it enter RequestCallback, but then it stop and never enter ResponseCallback instead it tryis userId.Text to assign asnJson value which is null, because it doesn't enter ResponseCallback. When I do wrong, and why it never enter ResponseCallback?


Solution

  • Your ManualResetEvent is created with true as the argument, so it's already signalled to start with. That means the allDone.Wait() call will immediately continue... so CreateRequest will finish, and you'll immediately try to use the asnJson variable, which as you've said is null. That will kill the application, I suspect - so you never get a chance to get a response.

    Now, the solution to this is not to change the ManualResetEvent constructor - you shouldn't be waiting like that in the UI thread anyway! You'll block it, and you've removed the whole point of Windows Phone 7 making everything asynchronous to start with.

    Instead, your callbacks should use the dispatcher to call back into the UI thread when they've finished. Note that you should also have robust error handling in case anything goes wrong with the request.