почему этот код зависает при ожидании TransformBlock.Completion - PullRequest
0 голосов
/ 14 июня 2019

следующие блоки кода на 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 Ответ

6 голосов
/ 14 июня 2019

Здесь есть две проблемы.

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

...