2012-02-20 2 views
4

私はAzure Table Storageで動作するライブラリを作成しています。基本的なパターンは、与えられたHTTP要求がコンテンツストリームの数値結果を返し、ヘッダーの次の結果セットを指すポインタです。結果がストリームから読み込まれると、結果が生成されます。私はSystem.Net.Httpライブラリ(以前のMicrosoft.Net.Http)を使用しています。これは、最新バージョンではHttpClient.Sendと他の同期メソッドの同期バージョンが削除されています。新しいバージョンでは、タスクが使用されます。私は以前にタスクを使用しましたが、この複雑なものではありません。私はスタートを得るのに苦労しています。非自明なコードを新しい.NET非同期パターンに変換する - yieldループを処理する方法

非同期パターンに変換されたコールは、HttpClient.Send、response.Context.ContentReadSteamです。重要な部分が表示されるようにコードを整理しました。

var queryUri = _GetTableQueryUri(tableServiceUri, tableName, query, null, null, timeout); 
while(true) { 
    var continuationParitionKey = ""; 
    var continuationRowKey = ""; 
    using (var request = GetRequest(queryUri, null, action.Method, azureAccountName, azureAccountKey)) 
    { 
     using (var client = new HttpClient()) 
     { 
      using (var response = client.Send(request, HttpCompletionOption.ResponseHeadersRead)) 
      { 
       continuationParitionKey = // stuff from headers 
       continuationRowKey = // stuff from headers 

       using (var reader = XmlReader.Create(response.Content.ContentReadStream)) 
       { 
        while (reader.Read()) 
        { 
         if (reader.NodeType == XmlNodeType.Element && reader.Name == "entry" && reader.NamespaceURI == "http://www.w3.org/2005/Atom") 
         { 
          yield return XElement.ReadFrom(reader) as XElement; 
         } 
        } 
        reader.Close(); 
       } 
      } 
     } 
    } 
    if (continuationParitionKey == null && continuationRowKey == null) 
     break; 

    queryUri = _GetTableQueryUri(tableServiceUri, tableName, query, continuationParitionKey, continuationRowKey, timeout); 
} 

私が正常に変換した例は以下のとおりです。

誰もループ/イールドを新しいパターンに変換する方法についての提案はありますか?

ありがとうございます! Erick

+0

[HttpClientの.Net 4.5バージョン](http://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.110%29.aspx) [synchrouns 'Send()'メソッド](http://msdn.microsoft.com/en-us/library/hh159031%28v=vs.110%29.aspx)があります。万が一メトロスタイルのアプリを作ろうとしていますか? – svick

+0

私はそうではありませんが、何らかの理由でシンクローンが送られてきたのを見たことがありませんでした(私はasp.netプロジェクトから新しいライブラリを手に入れました)。私はライブラリの他のバージョンを見ていきます。ありがとう。 –

答えて

4

あなたが発見したように、asyncは現在最大でyieldで動作しません。同様のコード変換を行っても、目標はかなり異なります。

バッファを提供し、プロデューサ/コンシューマタイプのアプローチを使用するソリューションが2つあります。 System.Tasks.Dataflow.dllは、複雑なコードのバッファを管理するのに便利です。

他の解決策は、「非同期列挙子」を書くことです。これは概念的にコードが行うべきことに近いが、このソリューションはプロデューサ/コンシューマソリューションよりもはるかに複雑である。

は、「非同期列挙子」タイプはthis video on Rxで少し議論され、あなたはan experimental Rx package(これはRxのチームによって行われているにもかかわらず、それが実際に受信を使用していないことに注意してください)からダウンロードすることができます。

1

私はループ\収率をthis articleのような出力キューの形式に変換することをお勧めします。これはBlockingCollection<T>です。そのため、メソッドの呼び出し元は、結果をプッシュするキューを提供します。

キューは、プロデューサをコンシューマから切り離すため便利ですが、1つのオプションに過ぎません。より一般的には、呼び出し元は、取得したすべての結果に対して実行されるコールバックを提供します。そのコールバックは非同期的でなければならず、例えば別のタスクを開始することができます。

+0

私はこれを見てみるかもしれませんが、歩留まりパターンの理由の1つは、ライブラリ内のメモリをたくさん食べることを避けることです。消費者が商品を十分に速く引っ張らないようにするためのコードを追加すれば、かなり低く抑えることができます。 –

+0

@ErickT:コレクションのサイズを制限することができます。プロデューサは、新しいアイテムをプッシュできるかどうかをチェックし、それ以外の場合は待機します。しかし、私は上記のIAsyncEnumerableオプションが好きです。 –

関連する問題