Программа никогда не заканчивается, когда я использую await Console.Out.WriteLineAsync - PullRequest
0 голосов
/ 18 декабря 2018

Я использую библиотеку DataFlow в .NET 4.7.1. По какой-то причине моя программа никогда не завершает работу, когда у меня есть await Console.Out.WriteLineAsync(DateTime.Now.TimeOfDay.ToString()); в async лямбда-выражении ActionBlock конструктора.Он будет просто выводить поток строк DateTime.Now.TimeOfDay.ToString() и случайным образом останавливаться, никогда не достигая Console.WriteLine("Time elapsed:" + watch.Elapsed);, хотя в некоторых случаях я наблюдал, что консоль выводит "Finished Reading the file".

 class Program
    {
        public static async Task Main(string[] args)
        {
            int numberOfLines = 0;
            Console.WriteLine("Number of cores used:" + Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 2.0)));

            BufferBlock<string> queBuffer = new BufferBlock<string>(new DataflowBlockOptions { BoundedCapacity = 100000 });


            var processingBlock = new ActionBlock<string>(async inputline =>
            {
                Interlocked.Increment(ref numberOfLines);
                //Line that causes issue
                //await Console.Out.WriteLineAsync(DateTime.Now.TimeOfDay.ToString());
            }
            , new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 48,
                SingleProducerConstrained = true,
                BoundedCapacity = 500
            });

            queBuffer.LinkTo(processingBlock);
            //Start
            var watch = System.Diagnostics.Stopwatch.StartNew();
            Console.WriteLine("Processing started at:" + DateTime.Now);

            if (File.Exists(args[0]))
            {
                using (StreamReader sr = new StreamReader(args[0]))
                {
                    string line;
                    // Read and display lines from the file until the end of the file is reached.
                    while ((line = await sr.ReadLineAsync()) != null)
                    {
                        await queBuffer.SendAsync(line);
                    }
                }
                await Console.Out.WriteLineAsync("Finished Reading the file");
            }
            queBuffer.Complete();
            processingBlock.Complete();
            await Task.WhenAll(queBuffer.Completion, processingBlock.Completion);
            watch.Stop();
            Console.WriteLine("Time elapsed:" + watch.Elapsed);
            Console.WriteLine("Number of lines read:" + numberOfLines.ToString());           
        }
    }

Однако, если я вычеркну строку, вызывающую проблему, она сработает и прочитает все строки из текстового файла.W:\test>.\CompressAMS.exe token2-small.txt Number of cores used:24 Processing started at:12/17/2018 6:32:50 PM Finished Reading the file Time elapsed:00:00:00.3569824 Number of lines read:100000

1 Ответ

0 голосов
/ 18 декабря 2018

То, что у вас есть, это состояние гонки, когда вы закончите.Вы звоните Complete() в обоих блоках, заставляя блок обработки прекратить прием сообщений, и в этот момент в буфере все еще могут быть данные для передачи.Затем, когда вы ожидаете завершения обоих блоков, если буфер не отправил все свои сообщения, он никогда не завершится, и выполнение будет зависать на Finished Reading File.

Вы можете безопасно ожидать оба блока, но только вызовите Complete() в буфере и позволяют TDF распространять завершение на ваш блок обработки в нисходящем направлении:

queBuffer.LinkTo(processingBlock, new DataflowLinkOptions() { PropagateCompletion = true });
/******/
queBuffer.Complete();
await Task.WhenAll(queBuffer.Completion, processingBlock.Completion);
...