private static AsyncStream <TResult> ParallelizeStreamInternalAsync <T, TResult>(this AsyncStream <T> source, Func <T, CancellationToken, Task <TResult> > actionAsync, ParallelizeOption option) { var core = new ParallelizeCore(source.CancellationToken, option); var monitor = new ParallelMonitor <T>(option.MaxDegreeOfParallelism); var channel = Channel.CreateUnbounded <StreamedValue <TResult> >(); var task = Task.Run(async() => { try { using (core) { var parallelTasks = Enumerable.Range(0, option.MaxDegreeOfParallelism) .Select(i => ParallelizeCoreStreamAsync(core, actionAsync, source, channel, i, monitor)) .ToArray(); await Task.WhenAll(parallelTasks); } } catch (Exception e) { channel.Writer.Complete(e); throw; } channel.Writer.Complete(); ThrowOnErrors(option, core); }); return(new AsyncStream <TResult>(channel, task, source.CancellationToken)); }
private static Task ParallelizeCoreStreamAsync <T, TResult>(ParallelizeCore core, Func <T, CancellationToken, Task <TResult> > actionAsync, AsyncStream <T> source, ChannelWriter <StreamedValue <TResult> > resultsChannel, int index, ParallelMonitor <T> monitor) { return(Task.Run(async() => { while (await source.ChannelReader.WaitToReadAsync()) //returns false when the channel is completed { while (source.ChannelReader.TryRead(out StreamedValue <T> streamedValue)) { if (streamedValue.Status != ExecutionStatus.Succeeded) { continue; } var item = streamedValue.Item; monitor.SetActive(index, item); if (core.IsLoopBreakRequested) { await YieldNotExecutedAsync(resultsChannel, default, item);