【问题标题】:Issue running multiple tasks that returns the same result运行多个返回相同结果的任务的问题
【发布时间】:2019-04-13 01:25:27
【问题描述】:

我有下面的代码(简化为可读)。我的问题是,只要返回类型是值类型(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),则任务不再相同

【问题讨论】:

  • 旁注:bool? 不是引用类型。
  • @PauloMorgado 你是对的

标签: c# async-await


【解决方案1】:

为常见用例缓存任务。


编译器在使用async 关键字时生成的状态机使用AsyncTaskMethodBuilder&lt;TResult&gt; 结构。对于常见的用例,例如为数字返回 0 或为布尔值返回 truefalse,出于性能原因,它使用缓存任务。代码可以在reference source 中找到。


blog post about ValueTasks 更详细地描述了该行为。

【讨论】:

  • 非常感谢!
【解决方案2】:

这是因为 RunSimple 同步运行并返回一个常量值。我认为编译器将其替换为一个预先计算的任务。 附言Task.FromResult(true) 每次使用 TaskCompletionSource 创建一个新任务。

【讨论】:

    【解决方案3】:

    你应该使用:

    await Task.Run(() => Console.WriteLine(i));
    

    代替:

    Console.WriteLine(i);
    

    在 RunSimple() 方法中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 2013-06-24
      相关资源
      最近更新 更多