Reputation: 7449
I am trying to return an IEnumerable from a method that is backed by a BlockingCollection. The code pattern is:
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();
}
The problem is the enumerable returned from Execute() is always empty. The examples that I have seen all iterate the BlockingCollection in a Task. That seems like it won't work in this situation.
Does anyone know where I am going wrong?
To make things a little more clear, I am pasted the code that I'm executing to populate the collection. Perhaps there is something that causes the issue in here?
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();
});
Upvotes: 2
Views: 752
Reputation: 24383
You need to call results.CompleteAdding()
when you have finished adding items to the collection.
If you don't, the enumeration will never end and Count()
will never return.
Apart from that, the code you've posted is correct.
Upvotes: 3