为什么在正常线程或任务上使用异步/等待
本文关键字:任务 异步 等待 常线程 线程 为什么 | 更新日期: 2023-09-27 18:28:00
我读了很多关于异步和等待的文章,起初我没有理解,因为我没有正确理解线程或任务。但在掌握了两者之后,我想知道:如果你对线程感到满意,为什么要使用async/await
?
async/await的异步性可以通过线程信令或Thread.Join()
等来实现。这只是为了节省编码时间和"减少"麻烦吗?
是的,它是一种语法糖,使处理线程变得更容易,也使代码更容易维护,因为线程管理是由运行时完成的。await
立即释放线程,并允许该线程或另一个线程从它停止的地方恢复,即使是在主线程上完成的。
像其他抽象一样,如果你想完全控制隐藏的机制,那么你仍然可以自由地使用线程信令等实现类似的逻辑。
如果您有兴趣了解async/await
生成的内容,那么可以使用Reflector或ILSpy对生成的代码进行反编译。
阅读什么是异步&等待生成?以了解C#5.0代表您所做的工作。
如果await只是调用Task.Wait
,我们就不需要特殊的语法和新的API了。主要区别在于async/await
在等待完成时完全释放了当前线程。在异步IO期间,根本不涉及线程。IO只是内核内部的一个小数据结构。
async/await
在后台使用了基于回调的等待,并让它的所有糟糕之处(想想JavaScript回调…)都发挥了作用。
请注意,async不仅仅是将工作转移到后台线程(通常)。它释放所有涉及的线程。
将async
和await
与螺纹进行比较就像将苹果与管钳进行比较。从10000英尺的高度看,它们可能看起来很相似,但对于非常不同的问题,它们是非常不同的解决方案。
CCD_ 10和CCD_特别是,允许一个方法在等待某个操作时暂停自己。当方法暂停时,它返回给它的调用者(通常返回一个任务,该任务在方法完成时完成)。
我想你对线程很熟悉,它是关于管理线程的。在async
世界中,与线程最接近的并行是Task.Run
,它开始在后台线程上执行一些代码,并在该代码完成时返回已完成的任务。
CCD_ 14和CCD_。因此,它们在WPF/Win8/WinForms/Silverlight/WP应用程序的UI线程中工作得很好,在不占用线程池资源的情况下保持UI线程的响应性。它们在ASP.NET等多线程场景中也能很好地工作
如果你想找一本关于async
/await
的好介绍,我在博客上写了一本,里面有其他推荐阅读的链接。
线程和异步/等待功能之间有区别。
想象一下这样一种情况,您正在呼叫网络以从网络中获取一些数据。在这里,调用网络驱动程序的线程(可能运行在某个svchost进程中)会阻止自己,并消耗资源。
在Async/await的情况下,如果调用不是网络绑定的,它会使用SynchronizationContext将整个调用封装到一个回调中,该回调能够从外部进程获取回调。这释放了线程,线程将可供其他东西使用。
异步和并发是两种不同的东西,前者只是在异步模式下调用一些东西,而后者实际上是cpu绑定的。当您需要并发时,线程通常会更好。
我很久以前写过一篇博客来描述这些功能。C#5.0 vNext-新的异步模式
async/await
不使用线程;这是一大优势。它使您的应用程序保持响应,而不会增加线程固有的复杂性和开销。
其目的是使应用程序在处理长时间运行、I/O密集型操作时能够轻松保持响应。例如,如果你必须从网站上下载一堆数据,或者从磁盘上读取文件,那就太好了。在这种情况下,旋转一个(或多个)新线程是过分的。
一般规则是在处理CPU绑定操作时通过Task.Run
使用线程,在处理I/O绑定操作时使用async/await
使用线程。
Stephen Toub在async/await
上有一篇很棒的博客文章,我建议你阅读。