我的印象是让我们!在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服务.
正如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有一篇文章讨论基于异步工作流的各种模式,您可以在财务仪表板示例中找到一个全面的示例