-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Closed
Copy link
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedapi-suggestionEarly API idea and discussion, it is NOT ready for implementationEarly API idea and discussion, it is NOT ready for implementationarea-System.Collectionsin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged
Milestone
Description
EDIT: See #60106 (comment) for an API proposal.
Background and motivation
Attempting to adapt an IAsyncEnumerable<T> to an IEnumerable<T>, Blocking collection seems to be the ideal type. It can be used to generate an enumerable that waits until the IAsyncEnumerable<T> produces items:
public static IEnumerable<T> ToEnumerable<T>(this IAsyncEnumerable<T> asyncEnumerable)
{
var list = new BlockingCollection<T>();
async Task AsyncIterate()
{
await foreach (var item in asyncEnumerable)
{
list.Add(item);
}
list.CompleteAdding();
}
_ = AsyncIterate();
return list.GetConsumingEnumerable();
}This works well but there's no way to propagate exceptions to the consuming enumerable that may happen when enumerating the IAsyncEnumerable<T>. I'd like to write something like this:
public static IEnumerable<T> ToEnumerable<T>(this IAsyncEnumerable<T> asyncEnumerable)
{
var list = new BlockingCollection<T>();
async Task AsyncIterate()
{
try
{
await foreach (var item in asyncEnumerable)
{
list.Add(item);
}
list.CompleteAdding();
}
catch(Exception ex)
{
list.CompleteAdding(ex);
}
}
_ = AsyncIterate();
return list.GetConsumingEnumerable();
}CompleteAdding with an exception would propagate it to the caller and it would throw on synchronous enumeration. The only way to throw an exception today AFAIK is to use a cancellation token but that won't propagate the original exception.
API Proposal
namespace System.Collections.Concurrent
{
public class BlockingCollection<T> : IEnumerable<T>
{
public void CompleteAdding(Exception error);
}
}API Usage
public static IEnumerable<T> ToEnumerable<T>(this IAsyncEnumerable<T> asyncEnumerable)
{
var list = new BlockingCollection<T>();
async Task AsyncIterate()
{
try
{
await foreach (var item in asyncEnumerable)
{
list.Add(item);
}
list.CompleteAdding();
}
catch(Exception ex)
{
list.CompleteAdding(ex);
}
}
_ = AsyncIterate();
return list.GetConsumingEnumerable();
}Risks
None that I'm aware of.
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedapi-suggestionEarly API idea and discussion, it is NOT ready for implementationEarly API idea and discussion, it is NOT ready for implementationarea-System.Collectionsin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged