public IEnumerator <TItem> GetEnumerator() { var currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; var aggregatedNodes = NodeAggregator <TItem> .Aggregate(nodes); var resultQueue = new Queue <TItem>(); var container = new StrongReferenceContainer(null); foreach (var item in source) { resultQueue.Enqueue(item); if (item != null) { foreach (var extractorNode in aggregatedNodes) { container.JoinIfPossible(RegisterPrefetch(extractorNode.ExtractKeys(item), extractorNode)); } } if (currentTaskCount == sessionHandler.PrefetchTaskExecutionCount) { continue; } while (container.JoinIfPossible(sessionHandler.ExecutePrefetchTasks())) { container.JoinIfPossible(ProcessFetchedElements()); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; } while (container.JoinIfPossible(sessionHandler.ExecutePrefetchTasks())) { container.JoinIfPossible(ProcessFetchedElements()); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } }
public async IAsyncEnumerator <TItem> GetAsyncEnumerator(CancellationToken token = default) { var currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; var aggregatedNodes = NodeAggregator <TItem> .Aggregate(nodes); var resultQueue = new Queue <TItem>(); strongReferenceContainer = new StrongReferenceContainer(null); var enumerationIdentifier = Guid.NewGuid(); async IAsyncEnumerable <TItem> ProcessItem(TItem item1) { resultQueue.Enqueue(item1); if (item1 != null) { foreach (var extractorNode in aggregatedNodes) { var fetchedItems = await RegisterPrefetchAsync(extractorNode.ExtractKeys(item1), extractorNode, enumerationIdentifier, token).ConfigureAwait(false); _ = strongReferenceContainer.JoinIfPossible(fetchedItems); } } if (currentTaskCount == sessionHandler.PrefetchTaskExecutionCount) { yield break; } while (strongReferenceContainer.JoinIfPossible( await sessionHandler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false))) { _ = strongReferenceContainer.JoinIfPossible(await ProcessFetchedElementsAsync(enumerationIdentifier, token).ConfigureAwait(false)); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; } if (source is IAsyncEnumerable <TItem> asyncItemSource) { await foreach (var item in asyncItemSource.WithCancellation(token).ConfigureAwait(false)) { await foreach (var p in ProcessItem(item).WithCancellation(token).ConfigureAwait(false)) { yield return(p); } } } else { var items = source is IQueryable <TItem> queryableSource ? await queryableSource.ExecuteAsync(token).ConfigureAwait(false) : source; foreach (var item in items) { await foreach (var p in ProcessItem(item).WithCancellation(token).ConfigureAwait(false)) { yield return(p); } } } while (strongReferenceContainer.JoinIfPossible( await sessionHandler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false))) { _ = strongReferenceContainer.JoinIfPossible(await ProcessFetchedElementsAsync(enumerationIdentifier, token).ConfigureAwait(false)); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } }