4

AzureTableStorageで動作するライブラリを作成しています。基本的なパターンは、特定のHTTPリクエストがコンテンツストリームに数値の結果を返し、ヘッダーに次の結果のセットへのポインタを返すというものです。結果がストリームから読み取られると、結果が生成されます。System.Net.Httpライブラリ(以前のMicrosoft.Net.Http)を使用しています。このライブラリは、最新バージョンでHttpClient.Sendの同期バージョンやその他の同期メソッドを削除しました。新しいバージョンはタスクを使用します。私は以前にタスクを使用しましたが、これほど複雑なものには使用していません。開始するのに苦労しています。

非同期パターンに変換された呼び出しは、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);
}

私が正常に変換したものの例を以下に示します。

client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ContinueWith(task =>
    {
        using (var response = task.Result)
        {
            if (response.StatusCode == HttpStatusCode.Created && action == HttpMethod.Post)
            {
                return XElement.Load(response.Content.ReadAsStreamAsync().Result);
            }
        }
    });

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

ありがとう!エリック

4

2 に答える 2

4

あなたが発見したように、今asyncのところはうまく機能しませんyield。これらは同様のコード変換を行いますが、目的はまったく異なります。

解決策は 2 つあります。1 つは、バッファーを提供し、プロデューサー/コンシューマー タイプのアプローチを使用することです。System.Tasks.Dataflow.dll複雑なコードでバッファを管理するのに役立ちます。

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

「非同期列挙子」タイプについては、 Rx に関するこのビデオで少し説明されており、実験的な Rx パッケージからダウンロードできます(これは Rx チームによって行われますが、実際には Rx を使用しないことに注意してください)。

于 2012-02-20T14:35:00.147 に答える
1

loop\yield を何らかの形式の出力キューに変換することをお勧めしますBlockingCollection<T>。したがって、メソッドの呼び出し元は、結果をプッシュするキューを提供します。

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

于 2012-02-20T08:36:51.207 に答える