转换块链接到多个目标,谓词无法按预期工作

时间:2019-07-09 01:17:17

标签: c# tpl-dataflow

我有一个基于谓词链接到动作块的变换块。

// Blocks
public TransformBlock<Document, Document> DocumentCreationTransformBlock =
    new TransformBlock<Document, Document>(async document => 
    {          
        return await CreateAsync(document); // REST API call that sets document.NewId
    }, 
    new ExecutionDataflowBlockOptions {
        BoundedCapacity = 100,
        MaxDegreeOfParallelism = 20
    });

public ActionBlock<Document> SplitPipelineActionBlock = 
    new ActionBlock<Document>(async document => 
    { // implementation obfuscated 
    },
    new ExecutionDataflowBlockOptions {
        BoundedCapacity = 100           
    }; 

// Shared block elements      
public DataflowLinkOptions CommonLinkOptions = new DataflowLinkOptions {
    PropagateCompletion = true };

// Link mesh
DocumentCreationTransformBlock.LinkTo(SplitPipelineActionBlock, 
    CommonLinkOptions, 
    document => !string.IsNullOrEmpty(document.NewId));

DocumentCreationTransformBlock.LinkTo(DataflowBlock.NullTarget<Document>(), 
    CommonLinkOptions);

transform块尝试通过REST API创建文档。它应使用Document更新NewId对象。因此,LinkTo谓词检查返回的Document是否具有NewId。

对于任何不符合此条件的对象,都有一个NullTarget块来清空TransformBlock

在测试中,我向管道发布了10,100个项目,并确认所有项目都成功返回了NewId。但是,有130个项目正在传递给NullTarget。当我再次在整个程序集上重新运行该程序时,有3000多个项目被传递到NullTarget。甚至先前已成功存储NewId的项目。

我怀疑SplitPipelineActionBlock BoundedCapacity已满,而LinkTo只是忽略了谓词,然后将要传递的项目传递给下一个LinkTo,这是一个问题,即NullTarget

如何做到这一点,以便所有项目都有机会发送到SplitPipeLineAction块?

1 个答案:

答案 0 :(得分:3)

当某项目可从源代码块获得时,它将一次将其提供给其链接;如果任何链接未收到该项目,则将该项目提供给下一个链接。没有区别为什么不使用链接。块确实将“也许以后”的答复与“否”的答复(Postponed vs Declined)区分开来,但是在任何一种情况下,都会尝试下一个链接来寻找一个可以 now 接受的链接块。 / p>

解决此问题的最佳选择是向空块链接添加谓词,该谓词是目标块链接的谓词的负数。

my_variable

这样,当Predicate<Document> predicate = document => !string.IsNullOrEmpty(document.NewId); DocumentCreationTransformBlock.LinkTo(SplitPipelineActionBlock, CommonLinkOptions, predicate); DocumentCreationTransformBlock.LinkTo(DataflowBlock.NullTarget<Document>(), CommonLinkOptions, document => !predicate(document)); 已满时,该项目被提供给null链接,由于断言失败而被拒绝,并且该项目保留在变换块输出缓冲区中,直到SplitPipelineActionBlock具有房间。