2013-01-12 41 views
3

我有一種方法,它從URL中提取HTML,通過解析它提取實體,並返回實體列表。這裏是樣品代碼:從Windows Phone應用程序的DownloadStringCompleted處理程序填充和返回實體

public List<Entity> FetchEntities() 
    { 
     List<Entity> myList = new List<Entity>(); 
     string url = "<myUrl>"; 
     string response = String.Empty; 
     client = new WebClient(); 
     client.DownloadStringCompleted += (sender, e) => 
     { 
      response = e.Result; 
      // parse response 
      // extract content and generate entities 
      // <---- I am currently filling list here 
     }; 
     client.DownloadStringAsync(new Uri(url)); 

     return myList; 
    } 

的問題是當異步調用與空myList進度控制的回報。我怎樣才能防止這一點。我的最終目標是返回填充列表。

而且這種方法是在一個單獨的類庫項目,並從Windows Phone應用程序調用,我必須保持它只有這樣。有沒有辦法做到這一點,或者我錯過了什麼?任何幫助將不勝感激。

回答

4

您可以通過回調到這樣的方法,並使其不帶任務的異步,所以你必須稍微更新方法的使用。

public void FetchEntities(
    Action<List<Entity>> resultCallback, 
    Action<string> errorCallback) 
{ 
    List<Entity> myList = new List<Entity>(); 
    string url = "<myUrl>"; 
    string response = String.Empty; 
    client = new WebClient(); 
    client.DownloadStringCompleted += (sender, e) => 
    { 
     response = e.Result; 
     // parse response 
     // extract content and generate entities 
     // <---- I am currently filling list here 

     if (response == null) 
     { 
      if (errorCallback != null) 
       errorCallback("Ooops, something bad happened"); 
     } 
     else 
     { 
      if (callback != null) 
       callback(myList); 
     } 
    }; 
    client.DownloadStringAsync(new Uri(url)); 
} 

另一種選擇是強制它是同步的。這樣

public List<Entity> FetchEntities() 
{ 
    List<Entity> myList = new List<Entity>(); 
    string url = "<myUrl>"; 
    string response = String.Empty; 
    client = new WebClient(); 
    AutoResetEvent waitHandle = new AutoResetEvent(false); 
    client.DownloadStringCompleted += (sender, e) => 
    { 
     response = e.Result; 
     // parse response 
     // extract content and generate entities 
     // <---- I am currently filling list here 

     waitHandle.Set(); 
    }; 
    client.DownloadStringAsync(new Uri(url)); 

    waitHandle.WaitOne(); 

    return myList; 
} 
4

這就是非阻塞異步編程的要點。您可以將回調作爲參數傳遞,並在其他地方處理結果,而不是嘗試返回它。

如果您需要返回結果,您可以使用this TPL library,我一直在使用它沒有問題一段時間了。

public Task<string> GetWebResultAsync(string url) 
    { 
     var tcs = new TaskCompletionSource<string>(); 
     var client = new WebClient(); 

     DownloadStringCompletedEventHandler h = null; 
     h = (sender, args) => 
       { 
        if (args.Cancelled) 
        { 
         tcs.SetCanceled(); 
        } 
        else if (args.Error != null) 
        { 
         tcs.SetException(args.Error); 
        } 
        else 
        { 
         tcs.SetResult(args.Result); 
        } 

        client.DownloadStringCompleted -= h; 
       }; 

     client.DownloadStringCompleted += h; 
     client.DownloadStringAsync(new Uri(url)); 

     return tcs.Task; 
    } 
} 

,把它正是你如何在.NET 4.0中

GetWebResultAsnyc(url).ContinueWith((t) => 
            { 
             t.Result //this is the downloaded string 
            }); 

使用TPL或:

var downloadTask = GetWebResultAsync(url); 
downloadTask.Wait(); 
var result = downloadTask.Result; //this is the downloaded string 

希望這有助於:)

+0

我嘗試使用上面的方法,我已經添加了包'System.Threading.Tasks'具有參考'System.Threading.Tasks.WP71'項目,但不能夠解決'Task'和'TaskCompletionSource'。你能幫我解決這個問題嗎? – Agent007

+1

你應該引用System.Threading.Tasks而不是System.Threading.Tasks.WP71編輯:程序集本身被稱爲System.Threading.Tasks.WP71並在代碼中添加一個using語句:using System.Threading.Tasks; –

+0

是的,我試過了,這是說不能解決類型'System.Threading.Tasks.TaskExtensions'。我該如何處理? – Agent007

相關問題