Не уверен, что код работает параллельно. Задачи в консольном приложении - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть этот код:

var dt = new DeveloperTest();
    var tasks = readers.Select(dt.ProcessReaderAsync).ToList();
    var printCounterTask = new Task(() => dt.DelayedPrint(output));
    printCounterTask.Start();

    Task.WhenAll(tasks).ContinueWith(x => dt.Print(output).ContinueWith(_ =>
    {
        dt.Finished = true;
    })).Wait();

    printCounterTask.Wait();

То, что это делает, это подготовка задач, которые будут выполняться, а затем начать (я думаю) параллельное выполнение, которое начинается с:

 printCounterTask.Start();

Вот что делает отложенная печать:

public async Task DelayedPrint(IOutputResult output)
        {
            while (true)
            {
                if (!Finished)
                {
                    //every 10 seconds should print. 
                    //at least one print even if the execution is less than 10 seconds
                    //as this starts in paralel with the processing
                    Task.Delay(10 * 1000).Wait();
                    await Print(output);
                }
                else
                {
#if DEBUG
                    Console.WriteLine("Finished with printing");
#endif
                    break;
                }
            }
        }

По сути, печать некоторого вывода, который задерживается каждые 10 секунд, затем, когда все задачи завершены, останавливает бесконечное l oop. если вы хотите увидеть весь код здесь https://github.com/velchev/Exclaimer-Test

Я не уверен, что этот

Task.WhenAll(tasks).ContinueWith(x => dt.Print(output).ContinueWith(_ =>
        {
            dt.Finished = true;
        })).Wait();

работает параллельно с printCounterTask.Start (); Когда я дебютирую, кажется, что это происходит как точка останова в! Завершенном коде, а затем в предложении else. Насколько я знаю, когда вы запускаете задачу, она запускается параллельно, поэтому все задачи должны выполняться параллельно. Задача - это представление потока, синтаксически которым легче управлять по сравнению со старым синтаксисом. Так что все эти потоки работают, и из-за лучшего синтаксиса проще сказать - подождите, пока все не закончатся sh, а затем измените флаг. Любое полезное объяснение будет оценено. Спасибо вам, друзья.

Ответы [ 2 ]

2 голосов
/ 29 апреля 2020

Код в основном правильный, как написано, но в конструкторе Task и ContinueWith есть некоторые нюансы, которые усложняют понимание и облегчают его взлом. Например, printCounterTask.Wait() не будет ждать завершения DelayedPrint, поскольку конструктор Task не понимает асинхронные делегаты.

Чтобы сделать код полностью корректным и намного легче читать и рассуждать, замените new Task / Start с Task.Run и замените ContinueWith на await:

var dt = new DeveloperTest();
var tasks = readers.Select(dt.ProcessReaderAsync).ToList();
var printCounterTask = Task.Run(() => dt.DelayedPrint(output));

await Task.WhenAll(tasks);
await dt.Print(output);
dt.Finished = true;

await printCounterTask;

Вы также обнаружите, что ваш код будет более понятным, если вы будете следовать соглашению об асинхронном суффиксе методы с Async.

Задача - это представление потока, синтаксически которым легче управлять по сравнению со старым синтаксисом.

Нет, не совсем. Задача - это Future - представление операции, которая может завершиться когда-нибудь в будущем. Эта «операция» не обязательно требует потока . Task.Run делает работу очереди в пул потоков, но в этом примере задача не всегда использует поток пула потоков (в частности, он не использует поток пула потоков во время await Task.Delay).

0 голосов
/ 29 апреля 2020

Вы отчасти правы. Задачи будут выполняться параллельно с

printCounterTask

, как и ожидалось. Однако задача не является представлением потока и не является синтаксическим подсвечиванием c, которое легче контролировать потоком. Здесь вы можете найти полезную информацию: https://www.dotnetforall.com/difference-task-and-thread/

Как правило, для вас важно понимать, что задачи используют потоки из ThreadPool.

Задача - это представление метода, который вы sh выполняете как фоновую работу (вы не хотите блокировать текущее выполнение), и для работы задаче необходим поток, но это не правда, что задача является потоком.

У вас может быть больше задач, чем доступных потоков в пуле потоков, что приведет к тому, что они ожидают в очереди доступного потока для выполнения.

Также примите во внимание эту задачу. Когда все не будут выполнять задачи за вас, вам придется выполнять их самостоятельно (реализация ProcessReaderAsyn c отсутствует, но если вы используете Task.Run, то все в порядке).

...