コード例 #1
0
        /// <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;
            }));
        }
コード例 #2
0
        /// <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;
        }
コード例 #3
0
        /// <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;
        }