让吧!/做!总是在新线程中运行异步对象?

时间:2015-06-17 18:41:20

标签: f#

从F#上的wikibook开始,有一小段文字说明:

  

让我们做什么!办?#

     

let!在自己的线程上运行async<'a>对象,然后立即   将当前线程释放回线程池。当let!返回时,   可以在新线程上继续执行工作流程   或者可能与工作流程开始时的线程不同。

我没有在书籍或网络上的任何其他地方找到这个事实(以粗体突出显示)。

对于所有let! / do!是否都是如此,无论异步对象包含什么(例如Thread.Sleep())以及它是如何启动的(例如Async.Start)?

查看github上的F#源代码,我无法找到在新(TP)线程上执行bind调用的位置。在代码中哪里发生了神奇的事情?

2 个答案:

答案 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