コード例 #1
0
        private DataflowPipeline <TItem> BuildNotEmpty <TItem>(
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            IProgress <byte> progress,
            CancellationToken cancellation)
        {
            var firstBlock    = ToTransformBlock(step, 0, context, cancellation);
            var previousBlock = firstBlock;

            for (var i = 1; i <= step.Blocks.Count - 1; i++)
            {
                var currentBlock = ToTransformBlock(step, i, context, cancellation);
                previousBlock.LinkTo(currentBlock, new DataflowLinkOptions {
                    PropagateCompletion = true
                });

                previousBlock = currentBlock;
            }

            var progressBlock = CreateProgressBlock(step, context, progress, cancellation);

            previousBlock.LinkTo(progressBlock, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            return(new DataflowPipeline <TItem>
            {
                InputBlock = firstBlock,
                Completion = progressBlock.Completion
            });
        }
コード例 #2
0
        private ActionBlock <PipelineItem <TItem> > BuildProgressBlock <TItem>(
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            CancellationToken cancellation)
        {
            return(new ActionBlock <PipelineItem <TItem> >(
                       x =>
            {
                if (x == null)
                {
                    return;
                }

                x.ProcessingStopwatch.Stop();
                context.Events?.Raise(e => e.OnItemEnded(x.Number, x.Item, step, context.StepContext.Task, x.ProcessingStopwatch.Elapsed));
                context.TaskEvents?.Raise(e => e.OnStepProgressed(x.Number, context.ExpectedItemsCount, x.ProcessingStopwatch.Elapsed, step, context.StepContext.Task));
            },
                       new ExecutionDataflowBlockOptions
            {
                NameFormat = "Progress",
                BoundedCapacity = 1,
                EnsureOrdered = true,
                CancellationToken = cancellation
            }));
        }
コード例 #3
0
 public DataflowPipeline <TItem> Build <TItem>(
     PipelineTaskStep <TItem> step,
     DataflowExecutionContext context,
     IProgress <byte> progress,
     CancellationToken cancellation)
 {
     return(step.Blocks.Count != 0
         ? BuildNotEmpty(step, context, progress, cancellation)
         : BuildEmpty(step, context, progress, cancellation));
 }
コード例 #4
0
        private TransformBlock <int, PipelineItem <TItem> > BuildMaterializeAndPostNextBlock <TItem>(
            IEnumerator <TItem> inputEnumerator,
            ITargetBlock <int> inputBlock,
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            CancellationToken cancellation)
        {
            return(new TransformBlock <int, PipelineItem <TItem> >(
                       i =>
            {
                var itemStartTs = DateTimeOffset.UtcNow;
                var sw = Stopwatch.StartNew();

                bool hasNextItem;

                try
                {
                    hasNextItem = inputEnumerator.MoveNext();
                }
                catch (Exception e)
                {
                    throw new TaskExecutionException(e, step, step.GetInputExceptionData(i));
                }

                if (hasNextItem)
                {
                    var pipelineItem = new PipelineItem <TItem>
                    {
                        Number = i,
                        Item = inputEnumerator.Current,
                        ProcessingStopwatch = sw
                    };

                    var materializationDuration = sw.Elapsed;
                    context.TotalInputMaterializationDuration += materializationDuration;
                    context.Events?.Raise(x => x.OnItemMaterialized(pipelineItem.Number, pipelineItem.Item, itemStartTs, materializationDuration, step, context.StepContext.Task));

                    PostNextInput(inputBlock, pipelineItem.Number + 1);
                    return pipelineItem;
                }
                else
                {
                    sw.Stop();
                    inputBlock.Complete();
                    return null;
                }
            },
                       new ExecutionDataflowBlockOptions
            {
                NameFormat = "MaterializeAndPostNextBlock",
                BoundedCapacity = 1,
                EnsureOrdered = true,
                CancellationToken = cancellation
            }));
        }
コード例 #5
0
        private DataflowPipeline <TItem> BuildEmpty <TItem>(
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            IProgress <byte> progress,
            CancellationToken cancellation)
        {
            var progressBlock = CreateProgressBlock(step, context, progress, cancellation);

            return(new DataflowPipeline <TItem>
            {
                InputBlock = progressBlock,
                Completion = progressBlock.Completion
            });
        }
コード例 #6
0
        private TransformBlock <PipelineItem <TItem>, PipelineItem <TItem> > BuildProcessingBlock <TItem>(
            PipelineBlock <TItem> block,
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            CancellationToken cancellation)
        {
            return(new TransformBlock <PipelineItem <TItem>, PipelineItem <TItem> >(
                       x =>
            {
                if (x == null)
                {
                    return x;
                }

                context.Events?.Raise(e => e.OnBlockStarted(block, x.Number, x.Item, step, context.StepContext.Task));
                var sw = Stopwatch.StartNew();

                try
                {
                    block.Body(x.Item);
                }
                catch (Exception e)
                {
                    throw new TaskExecutionException(e, step, block.GetExceptionData(x.Number));
                }

                sw.Stop();
                context.TotalBlockDurations.AddOrUpdate(block.Name, sw.Elapsed, (_, duration) => duration + sw.Elapsed);
                context.Events?.Raise(e => e.OnBlockEnded(block, x.Number, x.Item, step, context.StepContext.Task, sw.Elapsed));

                return x;
            },
                       new ExecutionDataflowBlockOptions
            {
                NameFormat = block.Name,
                MaxDegreeOfParallelism = block.MaxDegreeOfParallelism,
                BoundedCapacity = block.MaxDegreeOfParallelism,
                EnsureOrdered = true,
                CancellationToken = cancellation
            }));
        }
コード例 #7
0
        public DataflowPipeline Build <TItem>(
            IEnumerator <TItem> inputEnumerator,
            PipelineTaskStep <TItem> step,
            DataflowExecutionContext context,
            CancellationToken cancellation)
        {
            var inputBlock = BuildInputBlock(cancellation);

            var materializeAndPostNextBlock = BuildMaterializeAndPostNextBlock(inputEnumerator, inputBlock, step, context, cancellation);

            inputBlock.LinkTo(materializeAndPostNextBlock, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            ISourceBlock <PipelineItem <TItem> > previousBlock = materializeAndPostNextBlock;

            foreach (var block in step.Blocks)
            {
                var currentBlock = BuildProcessingBlock(block, step, context, cancellation);
                previousBlock.LinkTo(currentBlock, new DataflowLinkOptions {
                    PropagateCompletion = true
                });

                previousBlock = currentBlock;
            }

            var progressBlock = BuildProgressBlock(step, context, cancellation);

            previousBlock.LinkTo(progressBlock, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            return(new DataflowPipeline
            {
                Execute = () =>
                {
                    PostNextInput(inputBlock, 1);
                    return progressBlock.Completion;
                }
            });
        }
コード例 #8
0
 private ActionBlock <PipelineItem <TItem> > CreateProgressBlock <TItem>(
     PipelineTaskStep <TItem> step,
     DataflowExecutionContext context,
     IProgress <byte> progress,
     CancellationToken cancellation)
 {
     return(new ActionBlock <PipelineItem <TItem> >(
                x =>
     {
         x.ProcessingStopwatch.Stop();
         context.Events?.OnItemEnded(x.Number, x.Item, step, context.StepContext.Task, x.ProcessingStopwatch.Elapsed);
         PipelineProcessingUtils.ReportProgress(x.Number, step.Input.ExpectedItemsCount, progress);
     },
                new ExecutionDataflowBlockOptions
     {
         NameFormat = "Progress",
         BoundedCapacity = 1,
         EnsureOrdered = true,
         CancellationToken = cancellation
     }));
 }