我正在试验 Async CTP 并且非常喜欢它。然而,我确实有一个来自白皮书的问题来解释它。其中,它说:
重要的是要了解异步方法(如白皮书中列出的示例方法)不会在它们自己的线程上运行。
如果它们不在自己的线程上运行,那么异步行为如何工作?在(比如)UI 和“await”关键字创建的任务之间的现有线程上是否有很多上下文切换?
我正在试验 Async CTP 并且非常喜欢它。然而,我确实有一个来自白皮书的问题来解释它。其中,它说:
重要的是要了解异步方法(如白皮书中列出的示例方法)不会在它们自己的线程上运行。
如果它们不在自己的线程上运行,那么异步行为如何工作?在(比如)UI 和“await”关键字创建的任务之间的现有线程上是否有很多上下文切换?
当您调用异步方法时,它最初是同步的。在等待等待之前,它甚至没有机会异步。
在每个 await 表达式中,GetAwaiter()
都会调用您正在等待的 awaitable。然后IsCompleted
在等待者上测试该属性。如果任务已经完成,该方法会保持同步。
否则,OnCompleted
在 awaiter 上调用该方法,为其添加一个延续,然后在任务完成时回调该延续。async 方法本身在第一次遇到尚未完成的等待表达式时返回给调用者。
这个线程的确切性质取决于所涉及的等待者,但在异步 CTP for 中Task<T>
,TaskAwaiter
将使用当前任务调度程序来安排继续。对于 WinForms/Silverlight/WPF,这意味着如果您在 UI 线程上启动异步方法,它会在 UI 线程上继续。否则(例如,如果您已经在线程池线程上,或者您正在从控制台应用程序使用它),延续将在线程池线程上运行。当然,如果你真的想要,你可以自己更改当前的任务调度程序。
同样,不同的等待者不必使用TaskScheduler.Current
. 例如,我的协程延续基本上保持一个延续队列来执行,并继续执行直到它们执行。我的 ComeFrom 续集最终变得更加离奇:)
有关异步功能如何在后台工作的更多信息,请阅读我的Eduasync 博客系列,其中深入研究了它。
希望您总体上喜欢该功能...我认为这非常令人兴奋。
异步方法背后的思想是它不需要线程来运行,它只是使异步操作完成的调用和加入以线性方式流动。即如果您使用异步方法从文件中读取,它会同步调用文件读取的开始部分,然后暂停执行(即放弃当前线程以执行其他操作),直到操作系统级别操作完成并调用完成提供,这将取消暂停您的异步方法的其余部分(至少直到下一次等待)。