【问题标题】:Can the await keyword result in parallel code?await 关键字可以产生并行代码吗?
【发布时间】:2013-11-05 06:06:10
【问题描述】:

假设我有两个异步函数

Result1 result1 = await getResult1();
Result2 result2 = await getResult2();
doSomething(result1, result2);

理想情况下,我希望编译器分析我的方法,发现getResult2() 不依赖于getResult1() 的结果,并将其编译为安排两者同时运行的代码,等待两者的结果再继续。

问题 1:会发生这种情况吗?

问题 2:如果不是,我该如何实现,假设 Result1Result2 不共享基本类型,因此我不能使用 Task.WhenAll()

【问题讨论】:

  • 在 .NET 中“不共享基本类型”是非常不寻常的。您是否返回指针类型?
  • @BenVoigt 我的意思不是object...我当然可以装箱和拆箱,但这似乎不是惯用的方式
  • async-await 是关于异步而不是并行。

标签: c# .net task-parallel-library async-await


【解决方案1】:

会这样吗?

没有。 await 或多或少只是意味着“在以下任务完成之前不要继续执行代码”。

我如何做到这一点

先启动两个任务,然后等待它们都完成:

var firstTask = getResult1();
var secondTask = getResult2();
await Task.WhenAll(firstTask, secondTask);
doSomething(firstTask.Result, secondTask.Result);

【讨论】:

  • WhenAll 在这里不起作用,因为返回类型不同,对吧?
  • @GeorgeMauer 为什么不呢?调用await 的结果并不是那么有用。但无论如何我们都不需要它,因为我们自己有任务。如果没有存储任务并尝试从调用WhenAll 中获取结果,那么我们需要处理它。
  • 就像 Daniels 的回答一样,您可以在将参数传递给 doSomething-method 调用时等待。
  • @GeorgeMauer 什么,你的意思是把你明确说过的项目必须按给定的顺序运行,然后乱序执行,不。那是不可能的。如果您不想指定它们必须以给定的顺序开始,那很容易,我已经向您展示了许多可能的方法之一。但是,是的,如果您想改变行为,您将需要实际更改代码。
  • No await 是一个美化的.ContinueWith(,它重用了旧的 SynchronizationContext 以及在 await 作为函数参数传入之后发生的所有代码。所以你基本上做了getResult1().ContinueWith(() => getResult2(). ContinueWith(() => doSomething(result1, result2)));你明确地说“做这个,等待结果,然后做这个,等待结果,然后做最后一个函数”,所以编译器不能优化它,因为它会删除你的明确指示不要并行执行。
【解决方案2】:
  1. 不,在您的代码中,您正在等待第一个结果,然后再开始第二个操作。

  2. 先启动两个任务,然后等待它们:

    Task<Result1> task1 = getResult1();
    Task<Result2> task2 = getResult2();
    doSomething(await task1, await task2);
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多