为什么这段代码挂在`await TransformBlock.Completion`上

时间:2019-06-14 16:05:55

标签: c# .net-core task-parallel-library tpl-dataflow

await loader.Completion;上的以下代码块

我不知道为什么吗?

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;
        }
    }
}

1 个答案:

答案 0 :(得分:6)

这里有两个问题。

1)。您没有告诉您您已完成发布,因此不会Completion发出信号。

您需要先致电loader.Complete()

loader.Complete();
await loader.Completion;

2) TransformBlock的输出无处可去,因此该块 无法完成。直到清除其输出缓冲区,该块才能进入Completed状态。如果您不关心输出,则为ActionBlock。否则,您必须将块链接到其他内容,例如BufferBlock<string[]>,例如:

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

loader.LinkTo(results);

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

除非您在链接的选项中设置了PropagateCompletion选项,否则完成一个块不会传播到其他链接的块。在这种情况下,尽管没有理由将完成传播到BufferBlock