在Silverlight中对Web服务进行多次异步调用,将响应绑定到请求

时间:2011-09-25 12:03:07

标签: silverlight

我希望使用silverlight向不同的Web服务发送多个异步调用,并且能够匹配每个请求的响应。

假设我有一个包含n个项目的列表。每个项目代表一个Web服务的字符串URL。所以你可能有2个服务,但你也可能有7个。 现在,我有一个GUI,当我按下一个按钮时,迭代带有URL的列表,并向每个服务发送一个请求。您不知道可以调用多少服务,因此它必须是动态的。 我已经解决了发送部分,并得到了所有的响应,但是我的解决方案无法确定哪个响应涉及哪个请求。

private void startCall(object sender, RoutedEventArgs e) 
{
    var urls = {"http://this.is.the.first/service1", "http://this.is.thesecond/service2", "http://this.is.thethirt/service3"};
          foreach (var item in urls)
            {
                WebClient wc = new WebClient();
                wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);

                wc.DownloadStringAsync(new Uri(item));               
            }

void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {

            if (e.Error == null)
            {
                list_ResponseFromServer.Add(e.Result.ToString());
            }
        }

在此示例中,我在列表中有3个服务/项目。我也得到3个响应处理程序void wc_DownloadStringCompleted,但我不知道以什么顺序。 很明显我想拥有

ListRequest(A,B,C,D,E)

ListResponse(A,B,C,D,E)

但我不知道答案A是否需要比答案B,C

更长的时间

所以我可能会进入我的ListResponse(B,C,D,A,E) =>什么是失败

我看过一些带有2个异步调用的例子,但它们都是硬编码的。对于每个请求,响应他们有几个硬编码方法/处理程序。 如果有人可以帮助我通过对不同webServices的多个异步调用来解决这个问题,那将是很棒的

3 个答案:

答案 0 :(得分:1)

一种方法是使用委托来创建这样的捕获: -

private void startCall(object sender, RoutedEventArgs e) 
{
    var urls = {"http://this.is.the.first/service1", "http://this.is.thesecond/service2", "http://this.is.thethirt/service3"};
    foreach string item in urls)
    {
        Uri uri = new Uri(item);

        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += (s, args) =>
        {
             if (args.Error == null)
             {
                 // You can use the uri variable to determine which Uri this is a response to.
                 // NOTE: don't use item variable here.
                 list_ResponseFromServer.Add(args.Result);
             }
        };             
        wc.DownloadStringAsync(new Uri(item));               
    }
 }

修改:对评论的回复

通过某种方式,您需要一种方法来处理对该请求的响应。 Silverlight API没有提供内置机制,没有标准的解决方案。所以是的,您需要编写自己的代码,以便将异步响应与原始Url相关联(如果这对您很重要)。如果您更喜欢使用原始字符串网址,请在foreach代码块中添加另一个字符串变量,并为其指定item

您正在寻找的内容是为了保证响应到达的顺序与它们生成的顺序相匹配。唯一的方法是仅在先前的响应到达时发出每个请求。虽然这是可能的(我已经就此主题撰写了一系列blogs),但在这种情况下我不建议将其作为解决方案。

答案 1 :(得分:1)

您可以将自定义对象传递给DownloadStringAsync,因此我更改了一点Anthony代码:

var urls = {"http://this.is.the.first/service1", "http://this.is.thesecond/service2", "http://this.is.thethirt/service3"};

        var i = 0;
        var maxRequests = urls.Length;

        Dictionary<int, string> dict = new Dictionary<int,string>();

        foreach (string item in urls)
        {                
            WebClient wc = new WebClient();

            wc.DownloadStringCompleted += (s, args) =>
            {                                        

                if (args.Error == null)
                {                        
                   //add the the caller "id" and the response
                    dict.Add((int)args.UserState, args.Result);    
                }

                //here you test if it is the last request... if it is, you can
                //order the list and use it as you want 
                if (dict.Count == maxRequests)
                {
                    var orderedResults = dict.OrderBy(a => a.Key);                        
                }

            };

            wc.DownloadStringAsync(new Uri(item), i++);
        }
    }

答案 2 :(得分:0)

for (int i = 0; i < urls.Count; i++)
           {
            if (uri.AbsoluteUri.ToString().Equals(urls[i]))
            {
                list_ResponseFromServer.RemoveAt(i);
                list_ResponseFromServer.Insert(i, args.Result);
            }
        }

这是我的快速黑客如何将响应带入请求的相同顺序。如果一切都是独特的,你可以使用“休息”;太