当我尝试在.net中使用异步/等待时,我的项目最终发现几乎所有函数都有异步关键字,因为当它们等待其他异步函数时,它们本身应该是异步的。
例如,当我在某个异步IO库中使用函数时:
async Task Foo(){
await file.ReadAsyc();
}那么调用Foo()的函数也应该是异步的。
async Task Bar() {
await Foo();
}最后,我发现很多函数都有异步关键字。
有什么不好的地方(性能受损还是其他)?
发布于 2014-08-21 05:56:21
让我们看看async修饰符的MSDN定义:
使用异步修饰符来指定方法、lambda表达式或匿名方法是异步的。如果在方法或表达式上使用此修饰符,则称为异步方法。
他们继续说:
该方法同步运行,直到到达其第一个等待表达式,此时该方法被挂起,直到等待的任务完成。同时,控件返回给方法的调用方,如下一节中的示例所示。 如果异步关键字修改的方法不包含等待表达式或语句,则该方法同步执行。编译器警告您注意任何不包含等待的异步方法,因为这种情况可能表示错误。
async关键字在与await组合时起作用。这是一个信号,告诉编译器“此方法应该作为状态机编译,因此控件可以返回给调用方,并在异步操作完成时继续进行,并恢复其余的代码作为延续”。
如果方法中没有await关键字,那么它将从开始到结束同步运行,但是状态的代码将被发出,这是一个重要的因素。
现在,当等待一个async方法时,编译器会生成一个状态机。这确实是有代价的,尽管框架团队确保它对代码性能的影响最小。更重要的是,在幕后有一个SynchronizationContext,它在您的await (除非明确声明没有)时流动,它负责封送返回到原始线程上的继续。
有关内部(特别是性能方面)的更多信息,请参见异步性能:http://msdn.microsoft.com/en-us/magazine/hh456402.aspx。
发布于 2014-08-21 12:07:08
有什么不好的地方(性能受损还是其他)?
通常,如果您使用的是真正的异步操作(通常是I/O绑定的),异步的任何性能下降都是由更大的可伸缩性和/或响应性更强的UI组成的。最重要的关键是:只有在通过分析证明性能是必须解决的问题时,才能优化性能。
正如其他人所指出的,async确实会导致生成一个状态机,它占用内存并具有更大的代码大小。对性能影响的最佳资源是Stephen的MSDN文章和Channel9视频。
请注意,您可以进行一个“廉价”优化:
async Task FooAsync() {
await file.ReadAsync();
}与以下相同:
Task FooAsync() {
return file.ReadAsync();
}这是一个很好的技巧,当您做诸如方法重载之类的事情时,并且不想多次增加async开销。但是,如果方法中有其他代码,那么可能只需要使用async和await。
发布于 2014-08-21 06:06:00
缺点是使用这些基于异步模式的方法的代码必须意识到它们异步工作。也就是说,每个调用异步方法的方法也必须转换为异步方法。
虽然异步/等待模式简化了异步编程,因为代码看起来是同步的,但是开发人员需要掌握多线程的高级知识,以确保他们的代码不会陷入死锁、同步问题和意外行为。
例如,IIS和ASP.NET托管的代码将需要特殊的专家化(ASP.NET异步页面、异步任务.)因为IIS进程模型与Windows上的常规可执行应用程序的行为不同。
最后,如果我们讨论的是一个简单的客户端应用程序(您的应用程序可能有无用的线程同步开销),那么多线程环境中的线程同步可能会有性能损失,但是一旦客户端应用程序需要大量I/O和并行化,异步编程将更好地工作,因为您将利用您的多核CPU。如果我们讨论GUI应用程序,异步编程将是在执行长时间运行的过程时避免UI阻塞的好方法。
https://stackoverflow.com/questions/25418932
复制相似问题