Task.delay在Task内部.跑步



这里有以下代码:

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秒的秒表结果。但我有11092223

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

我认为您的困惑可能来自await Task.Delay(1000);中的await关键字

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

在这一行的末尾:

await Task.WhenAll(tasks);

你实际上在等待他们中最慢的一个(或者最后一个开始的那个(。

为了满足您的期望,您的代码实际上应该是这样的:

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)

延迟总是近似的。

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

当任务调度程序选择在延迟完成后恢复代码时,您会受到限制。

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

因为您正在启动多个任务,所以您会看到所有这些每个任务的变量都会合成更大的延迟。

最新更新