从F#上的wikibook开始,有一小段文字说明:
让我们做什么!办?#
let!
在自己的线程上运行async<'a>
对象,然后立即 将当前线程释放回线程池。当let!
返回时, 可以在新线程上继续执行工作流程 或者可能与工作流程开始时的线程不同。
我没有在书籍或网络上的任何其他地方找到这个事实(以粗体突出显示)。
对于所有let!
/ do!
是否都是如此,无论异步对象包含什么(例如Thread.Sleep()
)以及它是如何启动的(例如Async.Start
)?
查看github上的F#源代码,我无法找到在新(TP)线程上执行bind调用的位置。在代码中哪里发生了神奇的事情?
答案 0 :(得分:2)
你觉得哪个部分的陈述令人惊讶?单个异步的部分可以在不同的线程池线程上执行,还是必须在每次绑定时释放并获取线程池线程?
如果它是后者,那么我同意 - 这听起来不对。查看code,只有少数地方在线程池上排队新工作项(即内部使用Async
的少数queueAsync
模块函数),{ {1}}生成一个非线程池线程并在那里运行continuation。单独绑定似乎不足以切换线程。
然而,声明的精神似乎与前者有关 - 不保证Async.SwitchToNewThread
块的某些部分将在同一个线程上运行。你运行的确切线程应该被视为一个实现细节,当你产生控制并等待一些结果时,你可以非常肯定你至少在某些时候会在不同的线程上登陆。
答案 1 :(得分:1)
没有。异步操作可能在当前线程上同步执行,也可能最终在另一个线程上完成。这完全取决于所讨论的异步API的实现方式。
请参阅Do the new C# 5.0 'async' and 'await' keywords use multiple cores?以获得不错的解释。 F#和C#异步的实现细节不同,但总体原则是相同的。
实现F#async
计算表达式的构建器是here。