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 2012-02-22 08:33:02

+0

你的代碼原始代碼適合我。你有沒有試過在你的'Task'中調試代碼,看看它爲什麼從不調用'Add()'?因爲這是最可能的解釋。 – svick 2012-02-22 11:45:36

回答

3

當您完成向集合添加項目時,您需要致電results.CompleteAdding()

如果你不這樣做,枚舉將永遠不會結束,Count()將永遠不會返回。

除此之外,您發佈的代碼是正確的。

+0

我應該補充一點。問題是該方法立即返回,並且枚舉總是空的。 – 2012-02-22 05:32:06

+0

'Count()'將阻塞,直到枚舉完成。你有沒有嘗試在'CompleteAdding()'上放置一個斷點? – 2012-02-22 06:11:53

+0

感謝您的回答。事實證明,我有一個無關的錯誤,導致CompleteAdding不被調用。謝謝! – 2012-02-22 19:00:43