/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The rows.</param> /// <param name="cancellationToken">A CancellationToken to stop execution</param> /// <returns></returns> public override IAsyncEnumerable <Row> Execute(IAsyncEnumerable <Row> rows, CancellationToken cancellationToken = default) { return(new AsyncEnumerable <Row>(yield => { var input = new GatedThreadSafeEnumerator <Row>(Operations.Count, rows, cancellationToken); AsyncMonitor monitor = new AsyncMonitor(); Task[] tasks = Operations .Select(async operation => { var clone = input.Select(r => r.Clone()); var result = operation.Execute(clone, cancellationToken); if (result == null) { await input.DisposeAsync(); return null; } var enumerator = result.GetAsyncEnumerator(cancellationToken); return Task.Run(async() => { try { while (await enumerator.MoveNextAsync()) { ; } } finally { using (await monitor.EnterAsync(cancellationToken)) { await enumerator.DisposeAsync(); monitor.Pulse(); } } }, cancellationToken); }) .Where(t => t?.Result != null) .Select(t => t.Result) .ToArray(); Task.WaitAll(tasks); return Task.CompletedTask; })); }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The rows.</param> /// <returns></returns> public override IEnumerable <Row> Execute(IEnumerable <Row> rows) { var input = new GatedThreadSafeEnumerator <Row>(Operations.Count, rows); var sync = new object(); foreach (var operation in Operations) { var clone = input.Select(r => r.Clone()); var result = operation.Execute(clone); if (result == null) { input.Dispose(); continue; } var enumerator = result.GetEnumerator(); ThreadPool.QueueUserWorkItem(delegate { try { while (enumerator.MoveNext()) { ; } } finally { lock (sync) { enumerator.Dispose(); Monitor.Pulse(sync); } } }); } lock (sync) while (input.ConsumersLeft > 0) { Monitor.Wait(sync); } yield break; }
/// <summary> /// Executes this operation /// </summary> /// <param name="rows">The rows.</param> /// <returns></returns> public override IEnumerable<Row> Execute(IEnumerable<Row> rows) { var input = new GatedThreadSafeEnumerator<Row>(Operations.Count, rows); var sync = new object(); foreach (var operation in Operations) { var clone = input.Select(r => r.Clone()); var result = operation.Execute(clone); if (result == null) { input.Dispose(); continue; } var enumerator = result.GetEnumerator(); ThreadPool.QueueUserWorkItem(delegate { try { while (enumerator.MoveNext()) ; } finally { lock (sync) { enumerator.Dispose(); Monitor.Pulse(sync); } } }); } lock (sync) while (input.ConsumersLeft > 0) Monitor.Wait(sync); yield break; }