异步{... AsyncAdd ...}和异步{... AsyncAdd ...}有什么区别?

ca9*_*3d9 2 f#

在以下代码中,do! ag.AsyncAdd (Some i)ag.AsyncAdd (Some i)(在函数中enqueue())均起作用。它们之间有什么区别?似乎do! ...会使入队和出队电话更加混杂?怎么样?

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
Run Code Online (Sandbox Code Playgroud)

rmu*_*unn 6

在任何F#计算表达式中,任何以结尾结尾的关键字都!倾向于表示“根据此块的规则专门处理此问题”。例如,在一个async { }块中,let!关键字的含义是“等待结果,然后将结果分配给此变量”,do!关键字的含义是“等待此异步操作,但丢弃结果,而不将其分配给任何对象”。如果您使用do!关键字,那么您就不在等待该操作的结果。

因此,使用函数中的do!关键字enqueue,您将执行以下十五次:

  • 开始一项AsyncAdd手术
  • 等待它完成
  • 打印“ => 1”(或2或3 ...)

如果没有一个do!关键字,你正在做的情况如下:

  • AsyncAdd尽快开始15项操作
  • 逐一踢完后,打印“ => 1”(或2或3 ...)

听起来您似乎还不完全了解F#的计算表达式在后台如何工作。我建议阅读Scott Wlaschin的优秀网站以获取更多了解:首先https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/然后是https://fsharpforfunandprofit.com/series/computation-expressions.html,当您阅读第二系列文章时,您将以一些现有知识为基础。