运行多个任务返回相同结果的问题

时间:2018-11-09 13:10:29

标签: c# async-await

我有下面的代码(简化为易于阅读)。我的问题是,列表中的任务完全相同,只要返回类型是一个值类型(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)

,任务将不再相同。

3 个答案:

答案 0 :(得分:3)

为常见用例缓存任务。


使用async关键字时,编译器生成的状态机使用AsyncTaskMethodBuilder<TResult>结构。对于常见的用例,例如为数字返回0或为布尔值返回truefalse出于性能原因,它使用缓存的任务。相应的代码可以在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()方法上。