Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's different between async { ... AsyncAdd ... } and async { ... do AsyncAdd ... }?

Tags:

f#

In the following code, both do! ag.AsyncAdd (Some i) or ag.AsyncAdd (Some i) (in the function enqueue()) work. What's the difference between them? It seems do! ... will make enqueuing and dequeuing calls more mixed? How?

open FSharpx.Control

let test () =
    let ag = new BlockingQueueAgent<int option>(500)

    let enqueue() = async { 
        for i = 1 to 15 do 
            // ag.AsyncAdd (Some i) // works too
            do! ag.AsyncAdd (Some i) 
            printfn "=> %d" i }

    async {
        do! [ for i = 1 to 10 do yield enqueue() ] 
            |> Async.Parallel |> Async.Ignore
        for i = 1 to 5 do ag.Add None
    } |> Async.Start

    let rec dequeue() =
        async {
            let! m = ag.AsyncGet()
            match m with
            | Some v ->
                printfn "<= %d" v
                return! dequeue()
            | None -> 
                printfn "Done" 
        }

    [ for i = 1 to 5 do yield dequeue() ] 
    |> Async.Parallel |> Async.Ignore |> Async.RunSynchronously
    0
like image 529
ca9163d9 Avatar asked May 31 '26 19:05

ca9163d9


1 Answers

Inside any F# computation expression, any keyword that ends with ! tends to mean "Handle this one specially, according to the rules of this block". E.g., in an async { } block, the let! keyword means "await the result, then assign the result to this variable" and the do! keyword means "await this asynchronous operation, but throw away the result and don't assign it to anything". If you don't use a do! keyword, then you are not awaiting the result of that operation.

So with a do! keyword inside your enqueue function, you are doing the following fifteen times:

  • Kick off an AsyncAdd operation
  • Wait for it to complete
  • print "=> 1" (or 2, or 3...)

Without a do! keyword, you are doing the following:

  • Kick off fifteen AsyncAdd operations as fast as possible
  • After kicking each one off, print "=> 1" (or 2, or 3...)

It sounds like you don't yet fully understand how F#'s computation expressions work behind the scenes. I recommend reading Scott Wlaschin's excellent site to gain more understanding: first https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/ and then https://fsharpforfunandprofit.com/series/computation-expressions.html so that when you read the second series of articles, you're building on a bit of existing knowledge.

like image 129
rmunn Avatar answered Jun 02 '26 20:06

rmunn