在F#的Wikibook中,有一小段内容是:
什么让!做?#
let!async<'a>在自己的线程上运行对象,然后立即将当前线程释放回线程池。当let!返回时,工作流的执行将继续在新的线程,这可能是也可能不是同一个线程工作流开始出来。
我在书中或网络上的其他地方都找不到这个事实(以粗体突出显示)。
是否所有let!/ do!不管异步对象包含什么(例如Thread.Sleep())以及如何启动(例如Async.Start),都是这样?
在github上的F#源代码中,我找不到在新(TP)线程上执行绑定调用的位置。魔术在代码中的哪里发生?
您觉得该声明的哪一部分令人惊讶?单个异步的部分可以在不同的线程池线程上执行,或者线程池线程必须在每个绑定上被释放和获取?
如果是后者,那么我同意——这听起来是错误的。查看代码,只有几个地方新的工作项在线程池上排队(即内部Async使用的几个模块函数queueAsync),并Async.SwitchToNewThread生成一个非线程池线程并在那里运行延续。单独的绑定似乎不足以切换线程。
然而,该声明的精神似乎是关于前者 - 不保证async块的各个部分将在同一线程上运行。您运行的确切线程应该被视为实现细节,并且当您放弃控制并等待某些结果时,您可以非常确定至少在某些时候您会进入不同的线程。