I need to implement a method in a Silverlight library, which calls a (non-wcf-)service via httpwebrequest, gets the response, then populates an object and returns it.
Because this is Silverlight, response comes back asynchronously, so I'm having trouble figuring out where this object should be populated and how it should be returned.
This is the code I have so far:
public MyObject GetMyObject
{
HttpWebRequest req = WebRequest.Create(MyUri) as HttpWebRequest;
req.Method = "GET";
req.Accept = "application/json";
req.BeginGetResponse((cb) =>
{
HttpWebRequest rq = cb.AsyncState as HttpWebRequest;
HttpWebResponse resp = rq.EndGetResponse(cb) as HttpWebResponse;
开发者_JAVA百科 string result;
using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
{
result = reader.ReadToEnd();
reader.Close();
}
}, req);
}
I think I can populate the object right after I do reader.ReadToEnd(), but where do I actually return it? I can't return it inside the callback function, but if I return it at the end of GetMyObject(), the object is not guaranteed to be populated since of the asynch callback.
Thanks in advance!
First of all you need to recognise that when a sequence of operations (which we usually call "code") includes an operation that completes asynchronously then the whole sequence is in fact asynchronous.
In the synchronous world we have functions that return a specified type. In the asynchronous world those functions return void and instead have delegates passed to them to be called (we call them callbacks) where the delegate accepts a parameter of the specified type.
Since your function internally steps into the asynchronous world so it must also (since it has become part of a sequence which is now asynchronous). So its signature needs to change. It would now look like this:-
public void GetMyObject(Action<MyObject> returnResult)
{
HttpWebRequest req = WebRequest.Create(MyUri) as HttpWebRequest;
req.Method = "GET";
req.Accept = "application/json";
req.BeginGetResponse((cb) =>
{
WebResponse resp = req.EndGetResponse(cb);
string json;
using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
{
json = reader.ReadToEnd();
reader.Close();
}
MyObject result = SomethingDoDeserialiseJSONToMyObject(json);
returnResult(result);
}, null);
}
You would then call this method using as follows approach:-
GetMyObject(result =>
{
Dispatcher.BeginInvoke(() =>
{
// Display result in UI
});
});
精彩评论