这里我有以下代码:
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。
我想我错过了什么,你能帮我解释一下原因吗?
发布于 2020-07-29 11:50:44
我假设您的混淆可能来自于await Task.Delay(1000);中的等待关键字
但这只适用于任务方法的内部工作。在循环中,下一次迭代将在执行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)。
发布于 2020-07-29 12:40:06
延迟总是近似的。
当任务调度程序选择运行传递给Task.Run的委托时,您会受到限制。它可能正在执行其他任务,并且不愿意启动更多的线程。或者,它可能会启动一个新的线程--虽然不慢,但也不是免费的,也需要花费时间。
任务调度程序在延迟完成后选择恢复代码的时间限制了您。
您还受到操作系统调度程序的限制,它可能会将CPU时间分配给其他进程/线程,并最终延迟执行代码的线程。
因为您要启动多个任务,所以您将看到所有这些每个任务变量组合成一个更大的延迟。
https://stackoverflow.com/questions/63152914
复制相似问题