首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Task.delay内部Task.Run

Task.delay内部Task.Run
EN

Stack Overflow用户
提问于 2020-07-29 11:47:03
回答 2查看 1.4K关注 0票数 1

这里我有以下代码:

代码语言:javascript
复制
var tasks = new List<Task>();

var stopwatch = new Stopwatch();
for (var i = 0; i < 100; i++)
{
    var person = new Person { Id = i };
    list.Add(person);
}

stopwatch.Start();
foreach (var item in list)
{
    var task = Task.Run(async () =>
    {
        await Task.Delay(1000);
        Console.WriteLine("Hi");
    });
    tasks.Add(task);
}

await Task.WhenAll(tasks);
stopwatch.Stop();

我假设在秒表的结果中我将有大约100秒的。但我有1,1092223

我想我错过了什么,你能帮我解释一下原因吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-29 11:50:44

我假设您的混淆可能来自于await Task.Delay(1000);中的等待关键字

但这只适用于任务方法的内部工作。在循环中,下一次迭代将在执行Task.Run之后立即执行。因此,所有的任务都将连续启动,然后并行运行。(当然,只要系统有空闲线程,系统就会注意如何、何时和顺序地执行这些线程。

在这一行的最后:

代码语言:javascript
复制
await Task.WhenAll(tasks);

实际上,您需要等待其中最慢的(或者是从最后开始的)。

要充分满足您的期望,您的代码实际上应该如下所示:

代码语言:javascript
复制
public async Task RunAsPseudoParallel()
{
    List<Person> list = new List<Person>();

    var stopwatch = new Stopwatch();
    for (var i = 0; i < 100; i++)
    {
        var person = new Person { Id = i };
        list.Add(person);
    }

    stopwatch.Start();
    foreach (var item in list)
    {
        await Task.Run(async () =>
        {
            await Task.Delay(1000);
            Console.WriteLine("Hi");
        });
    }
    stopwatch.Stop()
}

免责声明:但是这段代码非常荒谬,因为它使用异步功能来实现同步过程。在这个场景中,您可以简单地省略Task.Run调用并使用一个简单的Thread.Sleep(1000)

票数 2
EN

Stack Overflow用户

发布于 2020-07-29 12:40:06

延迟总是近似的。

当任务调度程序选择运行传递给Task.Run的委托时,您会受到限制。它可能正在执行其他任务,并且不愿意启动更多的线程。或者,它可能会启动一个新的线程--虽然不慢,但也不是免费的,也需要花费时间。

任务调度程序在延迟完成后选择恢复代码的时间限制了您。

您还受到操作系统调度程序的限制,它可能会将CPU时间分配给其他进程/线程,并最终延迟执行代码的线程。

因为您要启动多个任务,所以您将看到所有这些每个任务变量组合成一个更大的延迟。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63152914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档