Waitgroups in F#

Our example demonstrates how to wait for multiple asynchronous operations to finish using F#’s Async workflow and Task parallel library.

open System
open System.Threading.Tasks

// This is the function we'll run in every task.
let worker (id: int) = async {
    printfn "Worker %d starting" id
    // Sleep to simulate an expensive task.
    do! Async.Sleep 1000
    printfn "Worker %d done" id
}

[<EntryPoint>]
let main argv =
    // Create a list of worker tasks
    let tasks = 
        [1..5]
        |> List.map (fun i -> worker i |> Async.StartAsTask)

    // Wait for all tasks to complete
    Task.WhenAll(tasks) |> Async.AwaitTask |> Async.RunSynchronously

    // Note that this approach has no straightforward way
    // to propagate errors from workers. For more
    // advanced use cases, consider using F#'s `Async.Catch`
    // or other error handling mechanisms.

    0 // return an integer exit code

To run the program:

$ dotnet fsi waitgroups.fsx
Worker 1 starting
Worker 2 starting
Worker 3 starting
Worker 4 starting
Worker 5 starting
Worker 1 done
Worker 2 done
Worker 3 done
Worker 4 done
Worker 5 done

The order of workers starting up and finishing is likely to be different for each invocation.

In this F# version:

  1. We define a worker function that takes an id and returns an Async<unit>. This is similar to the original Go function but uses F#’s async computation expression.

  2. In the main function, we create a list of tasks using List.map and Async.StartAsTask. This is analogous to launching several goroutines in the Go version.

  3. We use Task.WhenAll to wait for all tasks to complete, which is similar to the WaitGroup.Wait() in the Go version.

  4. We run the entire async workflow synchronously using Async.RunSynchronously.

  5. Error handling in this simple example is not explicitly addressed, but F# provides mechanisms like Async.Catch for more advanced error handling in asynchronous code.

This F# implementation achieves the same goal as the original Go code, demonstrating how to run multiple asynchronous operations concurrently and wait for their completion.