让!按顺序执行?

Rog*_*son 2 f# async-workflow

我的印象是让我们!在f#中,智能足以在并行中执行赋值序列.但是,以下示例显示不同的行为,a,b,c的分配似乎同步执行.

    let sleep sec =
        async
            {
                System.Threading.Thread.Sleep(sec * 1000)
                return sec
            }

    let bar = async 
                {
                    let! a = sleep 1
                    let! b = sleep 3
                    let! c = sleep 3
                    return a+b+c
                }

    let foo = Async.RunSynchronously(bar)
    printfn "%d" foo
Run Code Online (Sandbox Code Playgroud)

那是怎么回事?

如果我想在并行执行a,b,c,我应该使用Async.Parallell ... |> Async.RunSynchronously ...然后呢?

上面的示例是无用的,真正的用例就像查询数据库并同时调用一些web服务.

Tom*_*cek 7

正如Richard指出的那样,异步工作流仍然是完全顺序的.我认为任何试图进行全自动并行化的项目都没有完全成功,因为这样做太难了.

但是,异步工作流仍然可以使并行化更容易.关键是它们可以在不阻塞线程的情况下进行等待(这对于可伸缩性至关重要),并且它们还支持自动取消和简单的异常处理,使您的生活更轻松.有各种模式允许您在异步工作流中并行化代码.

  • 基于任务的你可以在后台启动你的三个任务,然后等到所有这些任务完成(这可能就是你所期望的,所以这里是如何明确写出来的):

    let bar = async  { 
      let! atask = sleep 1 |> Async.StartChild
      let! btask = sleep 3 |> Async.StartChild
      let! ctask = sleep 3 |> Async.StartChild
      let! a = atask
      let! b = btask
      let! c = ctask
      return a + b + c } 
    
    Run Code Online (Sandbox Code Playgroud)
  • 数据并行 - 如果您有多个相同类型的工作流,则可以创建一个使用并行运行所有这些工作流的工作流Async.Parallel.当您使用let!它时,它会运行所有三个任务并等待它们完成:

    let bar = async  { 
      let! all = Async.Parallel [ sleep 1; sleep 3; sleep 3 ]
      return all.[0] + all.[1] + all.[2] } 
    
    Run Code Online (Sandbox Code Playgroud)

Don Syme有一篇文章讨论基于异步工作流的各种模式,您可以在财务仪表板示例中找到一个全面的示例