tschmit007
tschmit007

Reputation: 7800

why does this code hangs on `await TransformBlock.Completion`

the following code blocks on await loader.Completion;

I just can't figure out why?

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;

namespace tests {
    class Program {
        static async Task Main(string[] args) {
            Planner pl = new Planner();
            Console.WriteLine(await pl.Count());
        }
    }

    public class Planner {
        private TransformBlock<int, string[]> loader;
        private int _im = 0;

        public Planner(int im = 5) {
            _im = im;
            loader =
                new TransformBlock<int, string[]>(
                    async i => {
                        Console.WriteLine(i);
                        await Task.Delay(1000);
                        return new string[] { i.ToString() };
                    }
               );
        }

        public async Task<long> Count() {
            foreach (int i in Enumerable.Range(1, _im))
                loader.Post(i);

            //loader.Complete(), same blocking
            await loader.Completion;
            return -1;
        }
    }
}

Upvotes: 0

Views: 504

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131533

There are two problems here.

1) You didn't tell the block you've finished posting so Completion will never be signalled.

You need to call loader.Complete() first :

loader.Complete();
await loader.Completion;

2) The TransformBlock's output has nowhere to go so the block can't complete. A block can't reach the Completed state until its output buffer is cleared. If you don't care about the output an ActionBlock. Otherwise you'll have to link the block to something else, like a BufferBlock<string[]>, eg :

var results=new BufferBlock<string[]>();

loader.LinkTo(results);

...
loader.Complete();
await loader.Completion;

Completing one block won't propagate to other linked blocks unless you set the PropagateCompletion options in the link's options. In this case though there's no reason to propagate completion to the BufferBlock

Upvotes: 8

Related Questions