2

BlockingCollectionがサポートするメソッドからIEnumerableを返そうとしています。コードパターンは次のとおりです。BlockingCollectionをメソッドからIEnumerableとして返す

public IEnumerable<T> Execute() { 
    var results = new BlockingCollection<T>(10); 
    _ExecuteLoad(results); 
    return results.GetConsumingEnumerable(); 
} 

private void _ExecuteLoad<T>(BlockingCollection<T> results) { 
    var loadTask = Task.Factory.StartNew(() => 
    { 
     //some async code that adds items to results 
     results.CompleteAdding(); 
    }); 
} 

public void Consumer() { 
    var count = Execute().Count(); 
} 

問題は、Execute()から返される列挙型は常に空です。私が見たすべての例は、Task内のBlockingCollectionを反復処理します。それはこのような状況ではうまくいかないようです。

誰かが間違っていると知っていますか?


さらに明確にするために、私が実行しているコードをペーストしてコレクションに挿入します。おそらくここに問題を引き起こす何かがありますか?

Task.Factory.StartNew(() => 
{ 
    var continuationRowKey = ""; 
    var continuationParitionKey = ""; 
    var action = HttpMethod.Get; 
    var queryUri = _GetTableQueryUri(tableServiceUri, tableName, query, continuationParitionKey, continuationRowKey, timeout); 
    while (true) 
    { 
     using (var request = GetRequest(queryUri, null, action.Method, azureAccountName, azureAccountKey)) 
     { 
      request.Method = action; 
      request.RequestUri = queryUri; 

      using (var client = new HttpClient()) 
      { 
       var sendTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); 
       using (var response = sendTask.Result) 
       { 
        continuationParitionKey = // stuff from headers 
        continuationRowKey = // stuff from headers 

        var streamTask = response.Content.ReadAsStreamAsync(); 
        using (var stream = streamTask.Result) 
        { 
         using (var reader = XmlReader.Create(stream)) 
         { 
          while (reader.Read()) 
          { 
           if (reader.NodeType == XmlNodeType.Element && reader.Name == "entry" && reader.NamespaceURI == "http://www.w3.org/2005/Atom") 
           { 
            results.Add(XNode.ReadFrom(reader) as XElement); 
           } 
          } 
          reader.Close(); 
         } 
        } 
       } 
      } 

      if (continuationParitionKey == null && continuationRowKey == null) 
       break; 

      queryUri = _GetTableQueryUri(tableServiceUri, tableName, query, continuationParitionKey, continuationRowKey, timeout); 
     } 
    } 
    results.CompleteAdding(); 
}); 
+1

これは問題を解決しませんが、すぐに 'Result'を使うつもりなら、' ... Async() 'メソッドを呼び出すことはあまりありません。 – porges

+0

あなたのコードの元のコードがうまく動作します。 'Task'のコードをデバッグして、なぜ' Add() 'を呼び出さないのか見てきましたか?それがもっともらしい説明だからです。 – svick

答えて

3

コレクションにアイテムを追加し終えたら、results.CompleteAdding()に電話する必要があります。

そうでない場合、列挙は決して終了せず、Count()は返されません。

それ以外は、あなたが投稿したコードは正しいです。

+0

これを追加しておきます。問題は、すぐにメソッドが返され、列挙は常に空であることです。 –

+0

'Count()'は、列挙が完了するまでブロックします。あなたは 'CompleteAdding()'にブレークポイントを置こうとしましたか? –

+0

答えをありがとう。無関係なバグがあり、CompleteAddingが呼び出されなかったことが判明しました。ありがとう! –

関連する問題