自从我的传播完成管道的最后一次更改以来,我的一个缓冲区块永远不会完成。让我总结一下什么在起作用,什么不再起作用:
以前的工作:
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
如果我取消注释注释行,一切正常,但显然该行不是必需的。
不知何故,我的BufferBlock B永远不会完成,即使链接到的块已完成并传播完成,而从链接的块接收所有缓冲的项目
答案 0 :(得分:0)
等待A完成A执行剩余代码,直到A完成。这就是等待的工作原理 - 它之后的代码被包装在一个续集中,准备完成等待的代码。所以在这种情况下,A在A完成后链接到A,所以我认为完成不会传播。
答案 1 :(得分:0)
我遇到了同样的问题 - 我的最后一个块是一个只是坐在那里等待完成的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