【问题标题】:WebClient - wait until file has downloadedWebClient - 等到文件下载完毕
【发布时间】:2012-03-15 20:47:58
【问题描述】:

我正在开发一个函数来返回从 xml 文件生成的集合。

最初,我使用本地 xml 文件进行测试,但现在我准备让应用程序从服务器下载真正的 xml 文件。由于需要为 WebClient 对象提供 OpenReadCompleted 事件处理程序,我正在努力了解如何做到这一点 - 我无法从中返回集合数据,并且在此处理程序执行时,原来的功能已经结束。

我的原代码如下:

public static ObservableCollection<OutletViewModel> GetNear(GeoCoordinate location)
{
    ObservableCollection<OutletViewModel> Items = new ObservableCollection<OutletViewModel>();

    // Load a local XML doc to simulate server response for location
    XDocument xDoc = XDocument.Load("SampleRemoteServer/outlet_list.xml");

    foreach (XElement outlet in xDoc.Descendants("outlet"))
    {
        Items.Add(new OutletViewModel()
        {
            Name = outlet.Attribute("name").Value,
            Cuisine = outlet.Attribute("cuisine").Value
        });
    }

    return Items;
}

如何在这个函数中加载文件,让事件处理程序运行,然后继续函数?

我能想到的唯一方法是添加一个循环来继续检查一个变量,该变量由事件处理程序代码更新......这听起来不是一个好的解决方案。

谢谢, 乔什

【问题讨论】:

  • 您不想阻塞 UI 线程,因此可能值得一读异步请求,即使这意味着您必须调整设计
  • 我已经开始研究 async/await 关键字了,谢谢!

标签: c# silverlight windows-phone-7


【解决方案1】:

您将foreach() 循环移动到完成的事件。

这确实意味着您无法从原始方法返回任何内容。将其设为void

这就是异步 I/O 的工作原理,最好习惯它。您将需要重新考虑您的设计。

【讨论】:

    【解决方案2】:

    您应该开始了解异步编程。 一种(老派)方法是实现一个公共事件并在调用类中订阅该事件。

    但是,使用回调更优雅。我创建了一个简单(无用,但在概念上仍然有效)的示例,您可以在此基础上进行构建:

    public static void Main(string[] args)
    {
      List<string> list = new List<string>();
    
      GetData(data =>
      {
        foreach (var item in data)
        {
          list.Add(item);
          Console.WriteLine(item);
        }
        Console.WriteLine("Done");
      });
      Console.ReadLine();
    }
    
    public static void GetData(Action<IEnumerable<string>> callback)
    {
      WebClient webClient = new WebClient();
      webClient.DownloadStringCompleted += (s, e) =>
        {
          List<string> data = new List<string>();
          for (int i = 0; i < 5; i++)
          {
            data.Add(e.Result);
          }
          callback(e.Error == null ? data : Enumerable.Empty<string>());
        };
    
      webClient.DownloadStringAsync(new Uri("http://www.google.com"));
    }
    

    如果您想加入 C# async 潮流 (link for WP7 implementation),您可以使用新的 asyncawait 关键字来实现它:

    public static async void DoSomeThing()
    {
      List<string> list = new List<string>();
      list = await GetDataAsync();
    
      foreach (var item in list)
      {
        Console.WriteLine(item);
      }
    }
    
    public static async Task<List<string>> GetDataAsync()
    {
      WebClient webClient = new WebClient();
      string result = await webClient.DownloadStringTaskAsync(new Uri("http://www.google.com"));
    
      List<string> data = new List<string>();
      for (int i = 0; i < 5; i++)
      {
        data.Add(result);
      }
      return data;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多