我有一个基于谓词链接到动作块的变换块。
// 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
块?
答案 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
具有房间。