【问题标题】:await await vs Unwrap()等待等待与 Unwrap()
【发布时间】:2016-01-21 01:04:10
【问题描述】:

给定一个方法,例如

public async Task<Task> ActionAsync()
{
    ...
}

有什么区别

await await ActionAsync();

await ActionAsync().Unwrap();

如果有的话。

【问题讨论】:

  • await ActionAsync().Unwrap(); 在两者之间肯定更容易阅读。这就是差异结束的地方。
  • 将基准添加到我的 asnwer。
  • @DrewKennedy 我不确定是不是,一旦你克服了最初的困惑,什么是双重等待,它有点像一个特殊的关键字,表示特定的东西

标签: c# async-await


【解决方案1】:

Unwrap() 创建一个新的任务实例,代表每次调用的整个操作。与await 相比,以这种方式创建的任务与原始内部任务不同。请参阅Unwrap() 文档,并考虑以下代码:

private async static Task Foo()
{
    Task<Task<int>> barMarker = Bar();

    Task<int> awaitedMarker = await barMarker;
    Task<int> unwrappedMarker = barMarker.Unwrap();

    Console.WriteLine(Object.ReferenceEquals(originalMarker, awaitedMarker));
    Console.WriteLine(Object.ReferenceEquals(originalMarker, unwrappedMarker));
}

private static Task<int> originalMarker;
private static Task<Task<int>> Bar()
{
    originalMarker = Task.Run(() => 1);;
    return originalMarker.ContinueWith((m) => m);
}

输出是:

True
False

更新 .NET 4.5.1 的基准测试:我测试了两个版本,结果表明带有双 await 的版本在内存使用方面更好。 我使用了 Visual Studio 2013 内存分析器。测试包括每个版本的 100000 次调用。

x64:

╔══════════════════╦═══════════════════════╦═════════════════╗
║ Version          ║ Inclusive Allocations ║ Inclusive Bytes ║
╠══════════════════╬═══════════════════════╬═════════════════╣
║ await await      ║ 761                   ║ 30568           ║
║ await + Unwrap() ║ 100633                ║ 8025408         ║
╚══════════════════╩═══════════════════════╩═════════════════╝

x86:

╔══════════════════╦═══════════════════════╦═════════════════╗
║ Version          ║ Inclusive Allocations ║ Inclusive Bytes ║
╠══════════════════╬═══════════════════════╬═════════════════╣
║ await await      ║ 683                   ║ 16943           ║
║ await + Unwrap() ║ 100481                ║ 4809732         ║
╚══════════════════╩═══════════════════════╩═════════════════╝

【讨论】:

  • 我非常感谢详细的答案、代码示例甚至基准测试!非常棒。
【解决方案2】:

不会有任何功能差异。

【讨论】:

  • 感谢您的确认,我会尽快接受。同时,此声明有任何参考吗?
  • @hatcyl 您需要什么参考资料? await 展开任务。这就是它的作用根据定义,它们是相等的。
  • @hatcyl Unwrap 返回一个表示Task&lt;Task&gt; 的内部任务的新任务。它几乎可以立即返回这样的任务;它不会是阻塞操作。如果任何一个返回的任务不相同,那么这将是两个进程之一中的错误。
  • @Servy 你什么时候想运行一个运行任务的任务?
  • @DavidKlempfner 使用ContinueWIth 时会出现很多情况,因为假设延续本身是异步的,它没有重载,所以你不得不解开它。它还提出了具有相同问题的其他操作,即它们被赋予一个操作并且不考虑它可能是异步的情况。还有WhenAny,它通过设计提供任务任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
  • 2018-05-04
  • 2020-05-09
  • 2021-09-15
相关资源
最近更新 更多