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