1

I have three different TransformBlock which take different inputs but spit out 3 derivations of the same abstract class, say AbstractBaseResult. This AbstractBaseResult has a property called IsSuccess that can be filtered.

Here is the rough equivalent code:

public abstract class AbstractBaseResult
{
    public bool IsSuccess {get; set;}
    public Exception Error {get; set;}
}

// For brevity I cannot include it here, but block1 and block2 are second/third generation predecessors of block3 in this dataflow
var block1 = new TransformBlock<Input1, DerivedResult1>(...);
var block2 = new TransformBlock<Input2, DerivedResult2>(...);
var block3 = new TransformBlock<Input3, DerivedResult3>(...);
var batchBlock = new BatchBlock<DerivedResult3>(1000);

var dataflowLinkOptions = new DataflowLinkOptions { PropagateCompletion = true };

block3.LinkTo(batchBlock, dataflowLinkOptions, x => x.IsSuccess);

var failures = new ConcurrentBag<Exception>();
var failBlock = new ActionBlock<AbstractBaseResult>(x => failures.Add(x.Error));
block1.LinkTo(failBlock, dataflowLinkOptions, x => !x.IsSuccess);
block2.LinkTo(failBlock, dataflowLinkOptions, x => !x.IsSuccess);
block3.LinkTo(failBlock, dataflowLinkOptions, x => !x.IsSuccess);

If I comment out block1/block2 linking to failBlock, then the application runs fine. However if all 3 are linked, then a fail condition on block3 causes the application to hang. Any idea what could be happening here or what I am missing?

Siddhartha Gandhi
  • 311
  • 1
  • 3
  • 11
  • 2
    This is example is not nearly complete enough to reproduce your issue, which in turn makes it hard to answer – TheGeneral May 06 '20 at 06:52
  • Can you show the line of code where the application hangs? I guess that you `await` for the `Completion` of some of these blocks somewhere. – Theodor Zoulias May 06 '20 at 10:17
  • 1
    You should take into consideration that according to how you have linked the blocks together, the `failBlock` will complete when any of the `block1`, `block2` or `block3` completes. Any exceptions that may occur to the remaining blocks after that, will not be added to the `failures` collection. – Theodor Zoulias May 06 '20 at 10:27
  • 2
    @TheodorZoulias I think you may have hit it in on the head - I overlooked that. What is the right way to do this? At a minimum it seems I need to turn off `PropagateCompletion` on the failure link. Update: Seems https://stackoverflow.com/questions/13510094/tpl-dataflow-guarantee-completion-only-when-all-source-data-blocks-completed has the answer. – Siddhartha Gandhi May 06 '20 at 13:05
  • 1
    Implementing the solution in the link above worked. So that was exactly what it is - the first block propagated completion, which left `block3` with some results that had no where to go, given the predicate on the `batchBlock`. Thank you. – Siddhartha Gandhi May 06 '20 at 13:31

0 Answers0