繁体   English   中英

不确定代码是否并行运行。 控制台应用程序中的任务

[英]Not sure if code runs in parallel. Tasks in console application

我有这个代码:

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秒延迟一次的output,然后当所有任务完成时停止无限循环。 如果你想看整个代码在这里https://github.com/velchev/Exclaimer-Test

我不确定这是否

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

与 printCounterTask.Start() 并行运行; 当我首次亮相时,它似乎作为 the.Finished 代码中的断点被击中,然后在 else 子句中也被击中。 据我所知,当您启动一项任务时,它会并行运行,因此所有任务都应该并行运行。 任务是线程的表示,与旧语法相比,它在语法上更容易控制。 所以所有这些线程都在运行,并且由于更好的语法更容易说 - 等到所有线程完成然后更改标志。 任何有用的解释将不胜感激。 谢谢小伙伴们。

编写的代码大部分是正确的,但是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为异步方法添加后缀的约定,您还会发现您的代码更清晰。

任务是线程的表示,与旧语法相比,它在语法上更容易控制。

一点都不。 任务是未来- 表示可能在未来某个时间完成的操作。 这种“操作” 不一定需要线程 Task.Run工作排队到线程池,但在此示例中,任务并不总是使用线程池线程(具体来说,它在await Task.Delay期间不使用线程池线程)。

你说对了一部分。 这些任务将与

打印计数器任务

正如预期的那样。 然而,任务不是线程的表示,也不是更容易控制线程的语法糖化。 在这里您可以找到有用的信息: https://www.dotnetforall.com/difference-task-and-thread/

一般来说,了解任务正在使用线程池中的线程对您来说很重要。

任务是您希望作为后台工作执行的方法的表示(您不想阻塞当前执行),并且任务需要线程才能操作,但任务不是线程.

线程池中的任务可能比可用线程多,这将导致它们在队列中等待可用线程以便执行。

还要考虑 Task.WhenAll 不会为您执行任务,您必须自己执行它们(缺少 ProcessReaderAsync 的实现,但如果您使用的是 Task.Run 就可以了)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM