C# TPL数据流块永远不会在完成时完成

C# TPL数据流块永远不会在完成时完成,c#,.net,task-parallel-library,dataflow,tpl-dataflow,C#,.net,Task Parallel Library,Dataflow,Tpl Dataflow,自从上次更改我的传播完成管道以来,我的一个缓冲块从未完成。让我总结一下什么是有效的,什么不再有效: 以前的工作: A.LinkTo(B, PropagateCompletion); B.LinkTo(C, PropagateCompletion); C.LinkTo(D, PropagateCompletion); D.Receive(); // everything completes A.LinkTo(B, PropagateCompletion); C.LinkTo(D, Propag

自从上次更改我的传播完成管道以来,我的一个缓冲块从未完成。让我总结一下什么是有效的,什么不再有效:

以前的工作:

A.LinkTo(B, PropagateCompletion);
B.LinkTo(C, PropagateCompletion);
C.LinkTo(D, PropagateCompletion);
D.Receive();

// everything completes
A.LinkTo(B, PropagateCompletion);
C.LinkTo(D, PropagateCompletion);

await A.Completion;
someWriteOnceBlock.Post(B.Count);
// B.Complete(); commented on purpose
B.LinkTo(C, PropagateCompletion);

D.Receive();

// Only A reaches completion
// B remains in 'waiting for activation'
// C executes but obviously never completes since B doesn't either
不再工作:

A.LinkTo(B, PropagateCompletion);
B.LinkTo(C, PropagateCompletion);
C.LinkTo(D, PropagateCompletion);
D.Receive();

// everything completes
A.LinkTo(B, PropagateCompletion);
C.LinkTo(D, PropagateCompletion);

await A.Completion;
someWriteOnceBlock.Post(B.Count);
// B.Complete(); commented on purpose
B.LinkTo(C, PropagateCompletion);

D.Receive();

// Only A reaches completion
// B remains in 'waiting for activation'
// C executes but obviously never completes since B doesn't either
如果我取消注释注释了注释行,一切都正常,但显然该行不是必需的


不知何故,我的缓冲块B从未达到完成,即使链接到它的块已完成并传播其完成,并且从它链接的块接收所有缓冲项。

通过等待A完成,在A完成之前,不会执行任何剩余代码。这就是等待的工作原理——代码被包装在一个延续中,准备完成等待的代码。所以在这个场景中,B在A完成后链接到A,所以我认为完成不会传播。

我有同样的问题-我的最后一个块是一个TransformBlock,它只是坐在那里等待完成

一个块只有在它没有剩余的输入要处理,它的所有输出都已处理并且已经完成的情况下才会完成,可以通过调用block.complete,也可以通过向链下游传播完成

我通过将最后一个块设置为ActionBlock来修复这个问题,因为这不会产生任何输出。以下是我的代码,它获取一系列文本文件并对其内容进行反序列化:

Dim maxDop = Environment.ProcessorCount
Dim executionOptions = New ExecutionDataflowBlockOptions With {.MaxDegreeOfParallelism = maxDop}
Dim linkOptions = New DataflowLinkOptions With {.PropagateCompletion = True}

Dim inputBlock = New BufferBlock(Of String)
Dim transformBlock = New TransformBlock(Of String, IEnumerable(of JsonObject))(Function(fileName) DeserialiseFromFileAsync(fileName)
Dim outputBlock As New BufferBlock(Of IEnumerable(of JsonObject))
Dim combineBlock = New ActionBlock(Of IEnumerable(of JsonObject))(Sub(col) ' Do something to add all the collections together)

inputBlock.LinkTo(transformBlock, linkOptions)
transformBlock.LinkTo(outputBlock, linkOptions)
outputBlock.LinkTo(combineBlock, linkOptions)

For fileNo = 1 To 10
    inputBlock.Post(String.Concat("JsonFile", fileNo, ".txt"))
Next

inputBlock.Complete() 'Complete the first block, propogation will handle the rest
Await combineBlock.Completion 'Await the last block completing

首先,你的意思可能是A与B相连(不是B与A相连),其次,你的解释只证实了等待A。完成是个问题,很明显我已经知道了,但它没有说明传播完成发生了什么,它只是被忽略了吗?你应该展示你的实际代码。@i3arnon我不能把整个代码都放进去,因为管道相当复杂,清理它只是为了保留相关部分需要很长时间,但更重要的是,我管道中的所有东西都是相当标准的,我所有的块都是链接的,一件东西进一件东西出来。周围的那些行等待是唯一不寻常的事情,它们正是我拥有它们的方式,我相信在我完美工作的管道的其余部分中没有任何东西可以解释取消注释注释的行使其工作,注释它阻止B完成。你最终在这方面运气好吗?a