代码之家  ›  专栏  ›  技术社区  ›  CACuzcatlan

在Silverlight WP7中伪造同步调用

  •  8
  • CACuzcatlan  · 技术社区  · 16 年前

     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();
    

    然后将响应字符串解析为方法返回的对象列表。

    我遇到的问题是,在Silverlight/WP7中没有同步调用的方法。如果我使用回调,我将在不同的函数中得到响应,并且无法从原始函数返回响应。有没有一种方法可以同步进行调用,或者从回调函数返回启动异步调用的方法?

    4 回复  |  直到 16 年前
        1
  •  11
  •   Adam Sills    16 年前

    continuation passing style '.

    下面是一个使用匿名函数和lambda的示例:

    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 );
    }
    

    这是解决方案的一半。下一部分,实际上是把它叫做。假设您有一个ICommand实例或更简单的实例,一个需要调用此函数并“获取字符串”的按钮单击事件。不是“获取字符串”,而是调用此函数并提供回调方法(这将是一个闭包)。

    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 );
        });
    }
    

    下面是一篇非常好的文章,进一步解释了这个概念: http://blogs.msdn.com/b/wesdyer/archive/2007/12/22/continuation-passing-style.aspx

        2
  •  2
  •   Jamey McElveen    15 年前

    首先,我建议尝试熟悉异步,但如果您真的想/需要将异步调用转换为同步调用,您可以使用 ManualResetEvent 以达到预期的效果。

    下面是一个快速示例,如果使用:

    public ManualResetEvent _event = new ManualResetEvent(false);
    
    ...
    {
        ...
        var wc = new WebClient();
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(ReadCompleted);
        wc.OpenReadAsync(uri);
    
        // block until async call is complete
        _event.WaitOne();
    }
    
    private static void ReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        ...
        // set event to unblock caller
        _event.Set();
    }
    

    现在代码将在行上阻塞 _event.WaitOne(); 直到 _event.Set(); 被称为。

        3
  •  1
  •   Phil    16 年前

    查看Wintellect的Power线程库,它允许您使用同步编程模型执行异步操作。

    http://csharperimage.jeremylikness.com/2010/03/sequential-asynchronous-workflows-in.html

        4
  •  -2
  •   Mick N    15 年前

    最好是异步执行此操作,以便用户可以继续与设备交互。

    我怀疑您这样做的原因是为了在您的请求完成之前防止用户与某些控件交互。

    可以接受的方法是隐藏或禁用在请求处理期间不应与之交互的UI元素。