我有下面的代码(简化为易于阅读)。我的问题是,列表中的任务完全相同,只要返回类型是一个值类型(bool / int)并且具有相同的值即可。如果结果是引用类型(例如bool?),或者例如返回不同的int值,任务将不再相等。
即使任务实际上可以正常工作(控制台记录所有6个值),我也不明白为什么这些任务是相等的,有人可以解释一下还是指向一些文档来解释这一点。
[TestMethod]
public async Task RunMultipleTasks()
{
var list = new List<int> {0, 1, 2, 3, 4, 5};
var tasks = list.Select(i => RunSimple(i)).ToList();
var x = await Task.WhenAll(tasks);
Assert.IsTrue(tasks[0]== tasks[1]);
}
private async Task<bool> RunSimple(int i)
{
Console.WriteLine(i);
return true;
}
我还注意到,如果我在RunSimple方法中添加延迟,或者删除异步并返回Task.FromResult(true)
,任务将不再相同。答案 0 :(得分:3)
为常见用例缓存任务。
使用async
关键字时,编译器生成的状态机使用AsyncTaskMethodBuilder<TResult>
结构。对于常见的用例,例如为数字返回0
或为布尔值返回true
或false
出于性能原因,它使用缓存的任务。相应的代码可以在reference source中找到。
此blog post about ValueTasks详细描述了该行为。
答案 1 :(得分:0)
这是因为RunSimple同步运行并返回一个常数。我认为编译器将其替换为一个预先计算的Task。 附言Task.FromResult(true)每次使用TaskCompletionSource创建一个新任务。
答案 2 :(得分:0)
您应该使用:
await Task.Run(() => Console.WriteLine(i));
代替:
Console.WriteLine(i);
在RunSimple()方法上。