WP7 app never exits BeginGetResponse and goes into

2019-02-10 02:24发布

问题:

I have the following code:

private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

            // End the operation
            Stream postStream = request.EndGetRequestStream(asynchronousResult);

            //Console.WriteLine("Please enter the input data to be posted:");
            //string postData = Console.ReadLine();
            string postData = "my data";

            // Convert the string into a byte array.
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Write to the request stream.
            postStream.Write(byteArray, 0, postData.Length);
            postStream.Close();

                // Start the asynchronous operation to get the response
                IAsyncResult result =
                      (IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);

        }

        private void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

            // End the operation
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();
            StreamReader streamRead = new StreamReader(streamResponse);
            string responseString = streamRead.ReadToEnd();
            Console.WriteLine(responseString);
            // Close the stream object
            streamResponse.Close();
            streamRead.Close();

            // Release the HttpWebResponse
            response.Close();
            allDone.Set();

            Dispatcher.BeginInvoke((Action)(() => Debug.WriteLine("George")));
        }

However when my code hits BeginGetResponse it never exits (and I do not hit a breakpoint in the GetResponseCallback function). I tried adding the BeginInvoke call, but I still never enter this method. This code works in a windows console app - it's on Windows Phone 7 that it doesn'teorg

Can anyone see what I am doing wrong?

Thanks.

回答1:

If you have created the HttpWebRequest on the UI thread, then make sure you don't block the UI thread, otherwise you can deadlock.

The sample from the desktop .NET you have linked isn't optimized for the current phone networking stack. You should change the code so that you create the HttpWebRequest on a background thread.



回答2:

I can't see what's wrong with your code (maybe a complete example of what you're trying to do may help) but here's a simple working example of a way of performing the action you want to do.
It posts some data to a URI and then passes the repsonse to a callback function:

Simply execute like this (use of a BackgroundWorker is not necessary but is recommended)

var bw = new BackgroundWorker();
bw.DoWork += (o, args) => PostDataToWebService("http://example.com/something", "key=value&key2=value2", MyCallback);
bw.RunWorkerAsync();

Here's the callback function it refers to:
(You can change this however is appropriate to your needs.)

public static void MyCallback(string aString, Exception e)
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        if (e == null)
        {
            // aString is the response from the web server
            MessageBox.Show(aString, "success", MessageBoxButton.OK);
        }
        else
        {
            MessageBox.Show(e.Message, "error", MessageBoxButton.OK);
        }
    });
}

Here's the actual method:

public void PostDataToWebService(string url, string data, Action<string, Exception> callback)
{
    if (callback == null)
    {
        throw new Exception("callback may not be null");
    }

    try
    {
        var uri = new Uri(url, UriKind.Absolute);
        var req = HttpWebRequest.CreateHttp(uri);

        req.ContentType = "application/x-www-form-urlencoded";
        req.Method = "POST";

        AsyncCallback GetTheResponse = ar =>
            {
                try
                {
                    var result = ar.GetResponseAsString();

                    callback(result, null);
                }
                catch (Exception ex)
                {
                    callback(null, ex);
                }
            };

        AsyncCallback SetTheBodyOfTheRequest = ar =>
            {
                var request = ar.SetRequestBody(data);

                request.BeginGetResponse(GetTheResponse, request);
            };

        req.BeginGetRequestStream(SetTheBodyOfTheRequest, req);
    }
    catch (Exception ex)
    {
        callback(null, ex);
    }
}

and here are the extension/helper methods it uses:

public static class IAsyncResultExtensions
{
    public static string GetResponseAsString(this IAsyncResult asyncResult)
    {
        string responseString;

        var request = (HttpWebRequest)asyncResult.AsyncState;

        using (var resp = (HttpWebResponse)request.EndGetResponse(asyncResult))
        {
            using (var streamResponse = resp.GetResponseStream())
            {
                using (var streamRead = new StreamReader(streamResponse))
                {
                    responseString = streamRead.ReadToEnd();
                }
            }
        }

        return responseString;
    }

    public static HttpWebRequest SetRequestBody(this IAsyncResult asyncResult, string body)
    {
        var request = (HttpWebRequest)asyncResult.AsyncState;

        using (var postStream = request.EndGetRequestStream(asyncResult))
        {
            using (var memStream = new MemoryStream())
            {
                var content = body;

                var bytes = System.Text.Encoding.UTF8.GetBytes(content);

                memStream.Write(bytes, 0, bytes.Length);

                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);

                postStream.Write(tempBuffer, 0, tempBuffer.Length);
            }
        }

        return request;
    }
}