2010-03-19 24 views
5

我在.NET中編寫的用於創建REST調用的大部分代碼都是同步的。由於Windows Phone上的Silverlight僅支持異步WebClient和HttpWebRequest調用,因此我想知道一個良好的異步模式適用於公開可進行REST調用的方法的類。順序WebClient請求的良好異步模式

例如,我有一個應用程序需要執行以下操作。

  1. 登錄並獲得令牌
  2. 從#1使用令牌,獲得專輯
  3. 從#1使用令牌的名單得到類別

我的類公開名單幾種方法:

  1. 登錄()
  2. GetAlbums()
  3. GetCategories()

因爲每個方法需要使用異步調用什麼,我需要做的是基本阻止呼叫登錄,直到它返回,這樣我可以調用GetAlbums()來調用Web客戶端。

什麼是在我的課中揭示這些方法的好方法?

回答

3

這實際上取決於你想用這個信息做什麼。例如如果您正試圖以顯示專輯/類別等的列表,來模擬這一方法是

  1. 有它實現INotifyPropertyChanged接口的一個或多個類別,並用來爲您的視圖的數據源(以新的PhoneListApplication中的Models文件夾下的文件爲例)
  2. 啓動異步操作以登錄並獲取令牌,使異步方法的回調爲您存儲令牌並調用將啓動異步的函數操作來獲取相冊和類別的列表。
  3. 用於異步操作以獲取相冊/類別列表的回調可以更新ObservableList(通過向其添加項目)。我想成像你有一個類的專輯和類別,每個都有一個可觀察的列表。無論如何,一旦你完成添加,只需調用NotifyPropertyChanged與您更改的屬性的名稱,並且您的數據應該顯示。

有一個明顯的問題,您想等待,直到您收到通過網絡回來的東西(例如,如果您想保留登錄頁面,直到您知道您已成功通過身份驗證) 。在這種情況下,您可以更改異步回調中的頁面。

你當然也可以做更有趣的事情,並有一個線程等待由異步回調設置的事件。我建議不要讓UI線程這樣做,因爲它限制了你有超時等事情的能力,而且通常很麻煩。

7

你可能需要看看反應器(Rx)框架擴展:

http://www.leading-edge-dev.de/?p=501

http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

[編輯:哦 - 找到一個很好的鏈接:] http://rxwiki.wikidot.com/101samples

他們提供一種「順序」事件的方式,僅在符合某些條件時才起作用 - 例如,假設您有一個方法「AuthenticationResult Authenticate(string user,string pass)」

你可以這樣做:

var foo = Observable.FromAsyncPattern<string, string, AuthenticationResult> 
    (client.BeginAuthenticate, client.EndAuthenticate); 
var bar = foo("username","password"); 
var result = bar.First(); 

有效地將異步方法,以一個同步。你可以擴展到包括「鏈接」:

var bar = foo("username", "password") 
    .Then(authresult => DoSomethingWithResult(authresult)); 

Neat stuff。 :)

1

我們與這個樣子的所有異步函數簽名寫我們的客戶端服務層:

public void MyFunction(
    ArtType arg, 
    Action<ReturnType> success, 
    Action<FailureType> failure); 

服務代碼沒有一個異步調用Web服務,而返回時,它會調用成功回調(如果調用成功)以及失敗回調(如果出現故障/異常)。然後調用代碼有點看起來是這樣的:

MyServiceInstance.MyFunction(
    blahVar, 
    returnVal => UIInvoker.Invoke(() => 
    { 
     //some success code here 
    }), 
    fault => UIInvoker.Invoke(() => 
    { 
     //some fault handling code here 
    })); 

(UIInvoker僅僅是一種實用工具,分派回從後臺線程的用戶界面。)

1

我把東西在一起更流暢一點。

Restful-Silverlight是我創建的一個庫,用於幫助Silverlight和WP7。

我已經包含下面的代碼,以顯示如何使用該庫從Twitter檢索推文。從Twitter雷斯特夫爾-Silverlight的檢索鳴叫

示例用法:

 

//silverlight 4 usage 
List<string> tweets = new List<string>(); 
var baseUri = "http://search.twitter.com/"; 

//new up asyncdelegation 
var restFacilitator = new RestFacilitator(); 
var restService = new RestService(restFacilitator, baseUri); 
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri); 

//tell async delegation to perform an HTTP/GET against a URI and return a dynamic type 
asyncDelegation.Get<dynamic>(new { url = "search.json", q = "#haiku" }) 
    //when the HTTP/GET is performed, execute the following lambda against the result set. 
    .WhenFinished(
    result => 
    { 
     textBlockTweets.Text = ""; 
     //the json object returned by twitter contains a enumerable collection called results 
     tweets = (result.results as IEnumerable).Select(s => s.text as string).ToList(); 
     foreach (string tweet in tweets) 
     { 
      textBlockTweets.Text += 
      HttpUtility.HtmlDecode(tweet) + 
      Environment.NewLine + 
      Environment.NewLine; 
     } 
    }); 

asyncDelegation.Go(); 

//wp7 usage 
var baseUri = "http://search.twitter.com/"; 
var restFacilitator = new RestFacilitator(); 
var restService = new RestService(restFacilitator, baseUri); 
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri); 

asyncDelegation.Get<Dictionary<string, object>>(new { url = "search.json", q = "#haiku" }) 
       .WhenFinished(
       result => 
       { 
        List<string> tweets = new List(); 
        textBlockTweets.Text = ""; 
        foreach (var tweetObject in result["results"].ToDictionaryArray()) 
        { 
         textBlockTweets.Text += 
          HttpUtility.HtmlDecode(tweetObject["text"].ToString()) + 
          Environment.NewLine + 
          Environment.NewLine; 
        } 
       }); 

asyncDelegation.Go(); 
 
+1

貌似REF URL以上下https://github.com/amirrajan/Restful現在 – Stonetip

+0

Silverlight的位已經被移動到軋製舊標籤 – Amir