Reputation: 8033
I have two asynchronous operations, so I have these functions:
// Returs Async<Person>
let GetPerson =
...
// Returs Async<Address>
let GetAddress =
...
What is the idiomatic way to execute them in parallel and get their results?
My starting point is this approach.
let MyFunc = async {
let! person = GetPerson()
let! address = GetAddress()
...
}
This works, but this runs the two operations sequentially.
I also tried this (sort of based on my C# experience).
let MyFunc = async {
let personA = GetPerson()
let addressA = GetAddress()
let! person = personA
let! address = addressA
...
}
But it doesn't work, it also runs the two operations sequentially.
What most of the documentation says is to use Async.Parallel
with a sequence, but the problem is that the result type of the two operations are different, so I cannot put them in a sequence.
let MyFunc = async {
let personA = GetPerson()
let addressA = GetAddress()
[personA; addressA]
|> Async.Parallel
...
}
This gives a compilation error, because the two values have different types. (And also, with this syntax, how could I get the actual results?)
What is the idiomatic way to do this?
Upvotes: 8
Views: 232
Reputation: 243041
The idiomatic approach is to start both computations using Async.StartAsChild
and then wait for their completion using a second let!
:
let MyFunc = async {
let! personWork = GetPerson() |> Async.StartChild
let! addressWork = GetAddress() |> Async.StartChild
let! person = personWork
let! address = addressWork
// (...)
}
Just calling GetPerson
does not actually start the work - unlike in C# where tasks are created started, F# workflows are just descriptions of the work to be done, so they need to be started explicitly. The Async.StartChild
operation gives you a workflow that starts the work and returns another workflow that can be used for wait for its completion.
Upvotes: 10