F#:异步返回之前 SwitchToThreadPool 的用途

发布于 2024-10-27 00:28:00 字数 516 浏览 1 评论 0原文

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

let asyncMethod f = 
    async {  
        do! Async.SwitchToNewThread() 
        let result = f() 
        do! Async.SwitchToThreadPool() 
        return result
    } 

在 return 语句之前切换到线程池的目的是什么?我理解为什么当异步块有更多工作要做时您可能希望从专用线程切换到线程池,但这里的情况并非如此。

这不是主要问题的一部分,但我也很好奇为什么 SwitchToNewThread 和 SwitchToThreadPool 返回 Async。是否存在您不想立即“执行!”的用例?这些任务?谢谢

In the MS docs for Async.SwitchToNewThread one of the examples given is:

let asyncMethod f = 
    async {  
        do! Async.SwitchToNewThread() 
        let result = f() 
        do! Async.SwitchToThreadPool() 
        return result
    } 

What is the purpose of switching to the thread pool immediately before a return statement? I understand why you might want to switch from a dedicated thread to the thread pool when the async block has more work to do but that is not the case here.

This is not part of the main question, but I'm also curious to know why SwitchToNewThread and SwitchToThreadPool return an Async. Is there ever a use case where you would not want to immediately "do!" these tasks? Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流星番茄 2024-11-03 00:28:00

这个例子可能更清楚,因为它没有演示任何真实场景。

然而,在返回之前切换到另一个线程是有充分理由的。原因是调用您的函数(例如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

我认为示例中使用的模式不太正确 - 异步工作流应始终返回到启动它们的 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 } 

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

The example could be clearer, because it doesn't demonstrate any real scenario.

However, there is a good reason for switching to another thread before return. The reason is that the workflow that calls your function (e.g. asyncMethod) will continue running in the context/thread that you switch to before returning. For example, if you write:

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

I think the pattern used in the example isn't quite right - asynchronous workflows should always return back to the SynchronizationContext on which they were started (e.g. if a workflow is started on GUI thread, it can switch to a new thread, but should then return back to the GUI thread). If I was writing asyncMethod function, I'd use:

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

To answer your second question - the reason why SwitchTo operations return Async<unit> and need to be called using do! is that there is no way to switch to a different thread directly. The only points where you get the rest of the workflow as a function (that you can execute on a new thread) is when you use do! or let! The Async<T> type is essentially just some object that gets a function (the rest of the workflow) and can execute it anywhere it wants, but there is no other way to "break" the workflow.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文