F#:在异步返回之前的SwitchToThreadPool的目的

Kei*_*ith 8 concurrency f# multithreading asynchronous

Async.SwitchToNewThread的MS文档中,给出的示例之一是:

let asyncMethod f = 
    async {  
        do! Async.SwitchToNewThread() 
        let result = f() 
        do! Async.SwitchToThreadPool() 
        return result
    } 
Run Code Online (Sandbox Code Playgroud)

在return语句之前立即切换到线程池的目的是什么?我理解为什么你可能想要在异步块有更多工作要做的时候从专用线程切换到线程池,但事实并非如此.

这不是主要问题的一部分,但我也很想知道为什么SwitchToNewThread和SwitchToThreadPool返回Async.有没有一个用例,你不想立即"做!" 这些任务?谢谢

Tom*_*cek 11

这个例子可能更清晰,因为它没有展示任何真实场景.

但是,之前切换到另一个线程是有充分理由的return.原因是调用函数的工作流(例如asyncMethod)将继续在返回之前切换到的上下文/线程中运行.例如,如果你写:

Async.Start (async {
  // Starts running on some thread (depends on how it is started - 'Async.Start' uses
  // thread pool and 'Async.StartImmediate' uses the current thread
  do! asyncMethod (fun () -> 
      Thread.Sleep(1000) ) // Blocks a newly created thread for 1 sec
  // Continues running on the thread pool thread 
  Thread.Sleep(1000) }) // Blocks thread pool thread
Run Code Online (Sandbox Code Playgroud)

我认为示例中使用的模式并不完全正确 - 异步工作流应始终返回到SynchronizationContext它们启动的位置(例如,如果工作流在GUI线程上启动,它可以切换到新线程,但应该返回回到GUI线程).如果我正在编写asyncMethod函数,我会使用:

let asyncMethod f = async {  
    let original = System.Threading.SynchronizationContext.Current
    do! Async.SwitchToNewThread() 
    let result = f() 
    do! Async.SwitchToContext(original)
    return result } 
Run Code Online (Sandbox Code Playgroud)

回答你的第二个问题 - SwitchTo操作返回Async<unit>和需要调用的原因do!是没有办法直接切换到不同的线程.你在哪里得到工作流的其余部分作为功能(你可以在一个新的线程执行)唯一的点是,当你使用do!let!Async<T>类型本质上只是一些对象,获取一个函数(工作流的其余部分),并可以执行它在任何想要的地方,但没有其他方法来"打破"工作流程.

  • @StephenSwensen,如果`SynchrnoizationContext.Current`是`null`,并且你调用`Post`或`Send`方法,它将在线程池线程上执行. - 另见http://msdn.microsoft.com/en-us/magazine/gg598924.aspx (3认同)