2012-03-15 55 views
1

我正在开发一个函数来返回从xml文件生成的集合。WebClient - 等到文件已经下载

最初,我使用本地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; 
} 

我怎样才能加载该文件在此功能中,有事件处理程序的运行,然后继续功能?

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

感谢, 乔希

+0

你不想阻止用户界面线程,因此它可能是值得的异步请求读了,即使这意味着你要调整你的设计 – 2012-03-15 20:54:52

+0

我已经开始看异步/等待关键字,谢谢! – Josh 2012-03-15 23:03:04

回答

1

你应该开始看看异步编程。 一种(老派)的方式是实施一个公共事件并在调用类中订阅该事件。

但是,使用回调更优雅。我掀起了一个简单的(无用,但仍概念有效)例如,你可以建立在:

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; 
} 
+0

当然,.Net 4.5并不适用于Window-Phone-7 ... – 2012-03-15 22:37:45

+0

看起来很有用,我发现这个应该让我在WP7上使用它,尽管我明天会着眼于它。 .. http://www.abhisheksur.com/2011/04/async-support-for-silverlight-and-wp7.html – Josh 2012-03-15 23:01:43

+0

您可以使用WP7应用程序的异步CTP:http://msdn.microsoft.com/zh-cn/ -us/vstudio/gg316360 – 2012-03-16 04:56:13

2

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

而这的确意味着你不能从原始方法返回任何东西。将其设为void

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