Let! executing in sequence?
I was under the impression that let! in f# was smart enough to excute sequences of assignments in parallell. However, the following sample displays a different behavior, assignment of a,b,c seems to execute synchronously.
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
Is that how it is/should be?
And if I want to execute a,b,c in parallell, am I supposed to use Async.Parallell ... |> Async.RunSynchronously ... then?
The above sample is ofcourse useless , the real use开发者_StackOverflow中文版case would be something like query a DB and call some webservices at the same time.
As Richard points out, asynchronous workflows are still fully sequential. I don't think that any projects attempting to do fully automatic parallelization have been fully successful, because doing that is just too difficult.
However, asynchronous workflows still make parallelization easier. The key thing is that they make it possible to do waiting without blocking threads (which is essential for scalability) and they also support automatic cancellation and easy exception handling to make your life easier. There are various patterns that allow you to parallelize code in asynchronous workflows.
Task-based you can start your three tasks in background and then wait until all of them complete (this is probably what you were expecting, so here is how to write that explicitly):
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 }
Data-parallel - if you have multiple workflows of the same type then you can create a workflow that runs all of them in parallel using
Async.Parallel
. When you then uselet!
it runs all three tasks and waits until they complete:let bar = async { let! all = Async.Parallel [ sleep 1; sleep 3; sleep 3 ] return all.[0] + all.[1] + all.[2] }
Don Syme has an article discussing various patterns based on asynchronous workflows and you can find a comprehensive example in financial dashboard sample
let!
, in an async
block (or more correctly "computation expression") executes the expression asynchronously but the block as a whole is still executed linearly. This is the benefit of async
computation expressions: making a sequence of dependent asynchronous operations much easier to write by performing continuation passing for you.
(Other types of computation expression provide their own semantics for let!
, yield!
, etc.)
To perform parallel/concurrent execution you need multiple async
expressions executed separately.
I was under the impression
You've misunderstood (quite understandably).
精彩评论