C# WebClient-等待文件下载完成

C# WebClient-等待文件下载完成,c#,silverlight,windows-phone-7,C#,Silverlight,Windows Phone 7,我正在开发一个函数来返回从xml文件生成的集合 最初,我使用本地xml文件进行测试,但现在我准备让应用程序从服务器下载真正的xml文件。我正努力想知道如何才能做到这一点,因为WebClient对象需要提供一个OpenReadCompleted事件处理程序-我无法从中返回收集数据,而且在该处理程序执行时,原始函数已经结束 我的原始代码如下: public static ObservableCollection<OutletViewModel> GetNear(GeoCoordinate

我正在开发一个函数来返回从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;
}
publicstaticobservelectiongetnear(地理坐标位置)
{
ObservableCollection Items=新的ObservableCollection();
//加载本地XML文档以模拟位置的服务器响应
XDocument xDoc=XDocument.Load(“SampleRemoteServer/outlet_list.xml”);
foreach(xDoc.substands中的XElement出口(“出口”))
{
添加(新的OutletViewModel()
{
Name=outlet.Attribute(“Name”).Value,
烹饪=出口。属性(“烹饪”)。价值
});
}
退货项目;
}
如何在此函数中加载文件、运行事件处理程序,然后继续此函数

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

谢谢, Josh

foreach()
循环移动到已完成的事件

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


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

您应该开始研究异步编程。 一种(传统的)方法是实现一个公共事件,并在调用类中订阅该事件

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

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

您不想阻止UI线程,因此可能值得阅读异步请求,即使这意味着您必须调整设计。我已经开始查看async/Wait关键字,谢谢!看起来很有用,我发现这个应该可以在WP7上使用,不过我明天会好好看看。。。您可以将异步CTP与WP7应用程序一起使用:
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;
}