Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
802 views
in Technique[技术] by (71.8m points)

multithreading - Faking synchronous calls in Silverlight WP7

I'm porting some code from the full .NET framework to the WP7 version and I'm running into an issue with synchronous vs async calls.

 string response;
 string requestString = GenerateReqString();
 HttpWebRequest req = (HttpWebRequest) WebRequest.Create("endpoint");
 req.Method = "POST";
 req.ContentType = "text/xml";

 req.ContentLength = requestString.Length;

 StreamWriter sw = new StreamWriter (req.GetRequestStream(), System.Text.Encoding.ASCII);
 sw.Write(requestString);
 sw.Close();

 StreamReader sr = new StreamReader(req.GetResponse().GetResponseStream());
 response = sr.ReadToEnd();
 sr.Close();

The response string is then parsed into a list of objects that is returned by the method.

The problem I'm having is that there isn't a way to make the call synchronously in Silverlight/WP7. If I use a call back I'll get the response in a different function and wont be able to return it from the original function. Is there a way to either make the call synchronously or return from the CallBack function back to the method that kicked off the async call?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to think about the problem differently. To make asynchronous things "feel" synchronous, the easiest way to do it is to restructure your code to make use of 'continuation passing style'.

In essence, instead of calling a function that returns a value and then you process that value, you call a function, passing an anonymous function as a delegate to it. The called function will then invoke the delegate, passing in the string.

Here is an example, which uses anonymous functions and lambdas:

void DoSomethingAsync( Action<string> callback ) {
    HttpWebRequest req; // TODO: build your request

    req.BeginGetResponse( result => {
        // This anonymous function is a closure and has access 
        // to the containing (or enclosing) function.
        var response = req.EndGetResponse( result );

        // Get the result string and call the callback
        string resultString = null; // TODO: read from the stream

        callback(resultString);
    }, null );
}

This is one half the solution. The next part, is to actually call this. Imagine you have an ICommand instance or simpler, a button click event that needed to call this function and "get the string". Instead of "getting the string" you call this function and supply a callback method (which will be a closure).

void btnGo_Click( object sender, EventArgs e ) {
    DoSomethingAsync( resultString => {
        // This anonymous function is called when the web request has
        // finished and has your string. 

        // Now that we have the string, we can go and process it.
        ProcessWebResponseResult( resultString );
    });
}

Here is a really good article explaining the concept further: http://blogs.msdn.com/b/wesdyer/archive/2007/12/22/continuation-passing-style.aspx


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...