ActionBlock.Complete.Wait(令牌)不等待管道完成

时间:2019-05-22 15:36:16

标签: c# tpl-dataflow

我有一个TPL数据流管道,消息的条件链接流可能在图片中所示的任何一个操作块处结束。 enter image description here

我还将PropogateCompletion设置为True,这与整个管道中使用的链接选项相同。

一旦我通过将上下文传递到第一个TransformBlock来启动流程,它将启动流程上下文,其中包含开始和结束时间以及一些有关处理记录的度量。

管道方法。

public void  Process(CancellationToken token = default)
        {
            var linkOptions = new DataflowLinkOptions {PropagateCompletion = true};
            var exBlockOptions = new ExecutionDataflowBlockOptions
                {CancellationToken = token, MaxDegreeOfParallelism = Environment.ProcessorCount};
            _context.Start();

            var setMessagesToStartStatus = new TransformBlock<IContext, IContext>(async context =>
            {
                await _mRepository.SetMessagesToStartStatus(token);
                return context;
            }, exBlockOptions);
            var autoMapMessageReferences =
                new TransformBlock<IContext, IContext>(async context =>
                    {
                        await _mRepository.SetAutoMapMessageReferences(token);
                        return context;
                    },
                    exBlockOptions);
            var messagesToProcess = new TransformManyBlock<IContext, AwsomeMessage>(
                async context =>
                {
                    var r = await _mRepository.GetPendingMessagesToProcess(token);
                    return r.ToList();
                }, exBlockOptions);
            var errActionBlock =
                new ActionBlock<AwsomeMessage>(async inMessage =>
                {
                    await _mRepository.SetToErrorState(inMessage.MessageId, inMessage.ErrorMessage, token);
                    _errorWorks.Add(inMessage);
                }, exBlockOptions);

            var printActionBlock = new ActionBlock<AwsomeMessage>(inMessage =>
            {

                Console.WriteLine(
                    $"ID :{inMessage.MessageId}, Error?: {inMessage.IsInError}, ErrorString :: {inMessage.ErrorMessage}");
                _processedWorks.Add(inMessage);
            }, exBlockOptions);
            var updateSourceSystem = EnrichSourceSystemTransBlock(token, exBlockOptions);
            var detoxReasonUpdate = EnrichDetoxReasonTransBlock(exBlockOptions);
            var awsomeActionMapping = EnrichAwsomeActionMappingTransBlock(token, exBlockOptions);
            var lateReasonMapToWorkAction = EnrichLateReasonTransBlock(exBlockOptions);
            var updateWithNarrationReason = EnrichReasonToOtherTransBlock(token, exBlockOptions);
            var crossAmendedByAndOtherReason = EnrichCrossSystemTransBlock(exBlockOptions);
            var PureEQDBookReplacement = EnrichPurexBookTransBlock(token, exBlockOptions);
            var bookHierarchyEnrichMessage = EnrichBookHierarchyTransBlock(token, exBlockOptions);

            //pipeline
            setMessagesToStartStatus.LinkTo(autoMapMessageReferences, linkOptions);
            autoMapMessageReferences.LinkTo(messagesToProcess, linkOptions);
            messagesToProcess.LinkTo(updateSourceSystem, linkOptions);
            updateSourceSystem.LinkTo(detoxReasonUpdate, linkOptions);
            detoxReasonUpdate.LinkTo(awsomeActionMapping, linkOptions);
            awsomeActionMapping.LinkTo(errActionBlock, linkOptions, x => x.IsInError);
            awsomeActionMapping.LinkTo(lateReasonMapToWorkAction, linkOptions, x => !x.IsInError);
            lateReasonMapToWorkAction.LinkTo(updateWithNarrationReason, linkOptions);
            updateWithNarrationReason.LinkTo(errActionBlock, linkOptions, x => x.IsInError);
            updateWithNarrationReason.LinkTo(crossAmendedByAndOtherReason, linkOptions, x => !x.IsInError);
            crossAmendedByAndOtherReason.LinkTo(PureEQDBookReplacement, linkOptions);
            PureEQDBookReplacement.LinkTo(errActionBlock, linkOptions, x => x.IsInError);
            PureEQDBookReplacement.LinkTo(bookHierarchyEnrichMessage, linkOptions, x => !x.IsInError);
            bookHierarchyEnrichMessage.LinkTo(errActionBlock, linkOptions, x => x.IsInError);
            bookHierarchyEnrichMessage.LinkTo(printActionBlock, linkOptions, x => !x.IsInError);


            //Create Context 
            setMessagesToStartStatus.Post(_context);

            //Kick off complete. -- Mark the head to say its complete.
            try
            {
                setMessagesToStartStatus.Complete();
                printActionBlock.Completion.Wait(token);
                errActionBlock.Completion.Wait(token);
                _context.Complete();
            }
            catch (AggregateException exception)
            {
                Debug.WriteLine(exception.Message);
                foreach (var exc in exception.InnerExceptions)
                {
                    Debug.WriteLine($"Err Msg = {exc.Message}, Stack Work = {exc.StackTrace} ");
                }

                throw exception.InnerExceptions.Single();
            }
        }

我尝试了Task.WhenAll,但它到底是怎么回事。它只是块。 由于传播完成是真的,我尝试了setMessagesToStartStatus.Complete.Wait()

当我完成此操作时,只要不做这件事就说任务已经完成并继续前进。

来自db的GetMessages是一个TransformManyBlock,当我仅传递一项进入错误块的测试数据时,由于甚至没有启动打印块,它现在进入挂起状态。所以完整不会影响。另一个问题是它没有等待。

已修复以下代码。

 var completeFalseLinkOptions = new DataflowLinkOptions(){PropagateCompletion = false};

    //Linking changes.
    .LinkTo(errActionBlock, completeFalseLinkOptions, x => x.IsInError);
        awsomeActionMapping.LinkTo(lateReasonMapToWorkAction, linkOptions, x => !x.IsInError);
        lateReasonMapToWorkAction.LinkTo(updateWithNarrationReason, linkOptions);
        updateWithNarrationReason.LinkTo(errActionBlock, completeFalseLinkOptions, x => x.IsInError);
        updateWithNarrationReason.LinkTo(crossAmendedByAndOtherReason, linkOptions, x => !x.IsInError);
        crossAmendedByAndOtherReason.LinkTo(PureEQDBookReplacement, linkOptions);
        PureEQDBookReplacement.LinkTo(errActionBlock, completeFalseLinkOptions, x => x.IsInError);
        PureEQDBookReplacement.LinkTo(bookHierarchyEnrichMessage, linkOptions, x => !x.IsInError);
        bookHierarchyEnrichMessage.LinkTo(errActionBlock, completeFalseLinkOptions, x => x.IsInError);
        bookHierarchyEnrichMessage.LinkTo(printActionBlock, linkOptions, x => !x.IsInError);

//and Complete Wait here.

setMessagesToStartStatus.Complete();
printActionBlock.Completion.Wait(token);
//manually complete the error block.
errActionBlock.Complete();
errActionBlock.Completion.Wait(token);
_context.Complete();

0 个答案:

没有答案