Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute two Async<> calls with different result types in parallel?

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?

like image 759
Mark Vincze Avatar asked Dec 29 '16 19:12

Mark Vincze


People also ask

How do you call async in parallel?

Use Promise. all for the parallel function calls, the answer behaviors not correctly when the error occurs. Caveat: It doesn't matter if the await calls are on the same line or on different lines, so long as the first await call happens after all of the asynchronous calls.

Do async tasks run in parallel?

There is no parallelism here, as the “async Task” does not automatically make something run in in parallel. This will spawn 2 threads, run them simultaneously, and return when both threads are done. This will create a list of Tasks to be run at the same time.

How do I make multiple calls from async?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

Can we achieve parallel programming through async and await?

so an asynchronous programming implemented using async and await in c# 4.5 can also be considered parallel programming? I would say yes.


1 Answers

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.

like image 58
Tomas Petricek Avatar answered Nov 12 '22 15:11

Tomas Petricek