我有这段代码,它是简化功能以证明问题的骨架:
var tasks = Enumerable.Range(0, 10)
.Select(laneNo => Task.Run(() => Console.WriteLine($"Starting generator for lane {laneNo}")));
for(int r=0; ;++r)
{
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
Console.WriteLine($"Iteration {r} at {DateTime.Now}");
}
我从没见过将“启动生成器”打印到控制台,但我确实看到每3秒执行一次迭代-某种原因导致这些任务无法进行(在真实代码中,它们运行了相当长的一段时间,但是删除不会影响到问题)。
为什么第一批任务未运行?我的理论是和Task.Delay
有关吗?
您的linq语句永远不会实现。诸如Select,Where,OrderBy之类的Linq运算符可作为构建块链接在一起,但直到您通过foreach运行它或使用不返回可枚举的运算符(例如ToArray,ToList,First,Last等)时,它们才被执行。
如果在末尾调用ToList,应该会看到所有任务正在执行,但是如果仅调用First,则应该只看到一个任务,因为原始Range的迭代将在第一个元素之后终止。
LINQ Select
已推迟执行;它仅定义一个迭代器,因此不会生成您的Task
。
您可以使用Task.WhenAll(IEnumerable<Task>)
,它将迭代并等待每个Task.WhenAll(IEnumerable<Task>)
,生成新的Task
,一旦提供的所有任务也都完成,该Task
将完成:
var tasks = Enumerable.Range(0, 10)
.Select(laneNo => Task.Run(() => Console.WriteLine($"Starting generator for lane {laneNo}")));
await Task.WhenAll(tasks);