Select in F#

Our example demonstrates how to use F#’s Async workflows and Async.AwaitAny to wait on multiple asynchronous operations. This is similar to the select statement in other languages, allowing us to handle multiple concurrent operations efficiently.

open System
open System.Threading.Tasks

let asyncOperation1 () = async {
    do! Async.Sleep 1000
    return "one"
}

let asyncOperation2 () = async {
    do! Async.Sleep 2000
    return "two"
}

[<EntryPoint>]
let main argv =
    let operations = [
        asyncOperation1()
        asyncOperation2()
    ]

    let results = 
        [1..2]
        |> List.map (fun _ -> 
            async {
                let! result = Async.AwaitAny operations
                printfn "received %s" result
            })
        |> Async.Parallel
        |> Async.RunSynchronously

    0

In this example, we define two asynchronous operations that simulate blocking operations (like RPC calls) using Async.Sleep. Each operation returns a string after a specific delay.

We then create a list of these operations and use List.map to create a sequence of async workflows. Each workflow uses Async.AwaitAny to wait for any of the operations to complete and print the result.

Finally, we use Async.Parallel to run these workflows concurrently and Async.RunSynchronously to execute them and wait for all to complete.

To run the program, save it as AsyncSelect.fs and use the F# compiler:

$ fsharpc AsyncSelect.fs
$ mono AsyncSelect.exe
received one
received two

Note that the total execution time is only about 2 seconds, even though we have delays of 1 and 2 seconds. This is because both operations are executed concurrently.

This example demonstrates how F#’s asynchronous programming model can be used to handle concurrent operations efficiently, similar to select statements in other languages.