2012-03-15 82 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的工作原理,更好地習慣它。你需要重新考慮你的設計。