Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# using Async.Parallel to run 2 tasks in parallel

Assuming I have these two functions:

let dowork n =
    async {
        do printfn "work %d" n
    }

let work i = async {
  do! Async.Sleep(2000)
  printfn "work finished %d" i }

How would I use Async.Parallel to run them concurrently and wait for both to finish before proceeding?

like image 389
JonnyBoats Avatar asked Apr 05 '13 03:04

JonnyBoats


2 Answers

As mentioned earlier, you just put your async functions in a sequence and pass them to Async.Parallel.

But, if you need to execute different jobs that return results of different types, you can use Async.StartChild:

let fn1 = async {
        do! Async.Sleep 1000
        printfn "fn1 finished!"
        return 5
    }

let fn2 = async {
        do! Async.Sleep 1500
        printfn "fn2 finished!"
        return "a string"
    }

let fncombined = async {
        // start both computations simultaneously
        let! fn1 = Async.StartChild fn1
        let! fn2 = Async.StartChild fn2

        // retrieve results
        let! result1 = fn1
        let! result2 = fn2

        return sprintf "%d, %s" (result1 + 5) (result2.ToUpper())
    }

fncombined
|> Async.RunSynchronously
|> printfn "%A"
like image 112
MisterMetaphor Avatar answered Jan 23 '23 13:01

MisterMetaphor


Async.Parallel takes a sequence of async. In this case I pass it a list.

[dowork 1; work 2]
|> Async.Parallel
|> Async.RunSynchronously
|> ignore

If you want to return different types of data use a Discriminated Union.

type WorkResults =
    | DoWork of int
    | Work of float32

let dowork n =
    async {
        do printfn "work %d" n
        return DoWork(n)
    }

let work i = async {
  do! Async.Sleep(2000)
  printfn "work finished %d" i 
  return Work(float32 i / 4.0f)
}

[dowork 1; work 2]
|> Async.Parallel
|> Async.RunSynchronously
|> printf "%A"

output

work 1
work finished 2
[|DoWork 1; Work 0.5f|]
like image 25
gradbot Avatar answered Jan 23 '23 12:01

gradbot