c# - await/async 与 "classic"异步(回调)

标签 c# asynchronous async-ctp c#-5.0

所以新的异步CTP很酷;这让我的生活变得轻松多了,而不必编写命名的回调方法,并使这些方法的意图更加清晰。

现在我已经开始使用它了,我想知道 async/await 和“经典”异步回调语法之间可能存在哪些差异。

以下是我想到的几个问题,但还有许多其他问题我现在不会想到,以后可能会想到。

  • 其中一个是否可以提供优于另一个的性能?
  • 其中一个的开销是否大于另一个?
  • 哪个更适合在高性能环境中使用?

最佳答案

答案很复杂,当前的 await 编译器实现在几个方面优于回调,但在某些情况下更差。

.NET 执行上下文:我们打算让 await 和 ContinueWith(...) 捕获和恢复 .NET 执行上下文。否则它不会通过 .NET 安全要求,因为那样您就可以获取任意的东西,例如凭据等,并将它们留在线程池中以供下一个工作项使用。对于“等待”,这是我们在内部构建中所做的调整,但这是在我们生成//BUILD 开发人员预览版之后。

内存分配:在多个方面,“await”在内存分配方面优于手动回调。关键是对于有很多等待的函数,你真正生成的是几个回调的等价物。如果您有 5 个线性执行顺序的等待,并且执行总是流到最后,那么等效项将需要 5 个回调。对于这 5 个回调中的每一个,都可以生成一个单独的 lambda 闭包对象和一个代表该特定 lambda 的委托(delegate)。在“等待”的情况下,编译器知道您不会将委托(delegate)对象用于其他任何事情。因此,整个方法共享 1 个闭包和 1 个委托(delegate),并使用内部状态机来跟踪您在方法中的位置。因此,对于这种情况,'await' 分配更少的对象,这实际上可以加快您的程序,因为对象太多 = GC 必须花费更多时间来确定什么是活的/死的。

捷径 “等待”还有比回调更高级的语义。在创建回调 lambda 的情况下,编译器无论如何都必须分配闭包和 lambda 的入口点委托(delegate)。对于“等待”,等待契约(Contract)允许为已经“完成”的等待对象提供更优化的代码路径。如果 awaitable 在 await 被评估之前说它已经“完成”,那么语义只是抽出结果的纯粹传递。这意味着编译器有机会延迟分配,直到您真正需要它,因此您永远不会支付闭包分配、委托(delegate)分配或调度成本,除非您确实需要它。当前的 Developer Preview 编译器包括这些性能优化。

Perf 的交易危险 如果您真的想绕过 .NET 安全模型,您可以想象这样一种情况,您可以通过避免执行上下文 package/restore 来获得一点 perf ,如果您绝对有信心永远不需要捕获/恢复上下文。但是,大多数 .NET 方法都会在幕后默默地执行此操作,因此您确实需要知道哪些方法可以在没有它的情况下为您提供原始访问权限。 .NET 的经验法则是,如果 API 在部分信任中可用(例如 Silverlight),那么 API 肯定会在调用时捕获上下文,然后恢复它,如果它是将执行转移到别处的 API(例如 ContinueWith、QueueUserWorkItem( ...), ETC。)。如果您滚动自己的线程池来对委托(delegate)进行排队,则可以绕过它,但很可能不需要它。

个人推荐使用await。这是更高的层次,这就是你想要的。我们已经付出了相当多的努力来尝试针对此版本对其进行调整,并且我们可能会进一步调整它。基于回调的 API 将受到更多限制,因为编译器在开始违反语言规则之前只能调整这么多。方法中的等待允许您拥有比回调更智能的闭包。 AND... await 比回调更直观地阅读/使用 :)

关于c# - await/async 与 "classic"异步(回调),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7870334/

相关文章:

c# - Windows UWP Pivot 轻扫 UI

ios - 关于使用完成 block 排队

asp.net-mvc - Asp.NET MVC 3 项目模板未显示

c# - 将依赖属性与异步 ctp 一起使用

c# - 使用 = 的条件逻辑运算符

C# MVC 和 Web API 应用程序架构

javascript - task.js 生成器/ promise 与异步回调

PHP 多个 Ajax 请求 : First request block second request

pattern-matching - "Iterating"通过异步方法

javascript - SignalR 服务 : Get message depending on user role