Asynchronous 使用BlockingQueueAgent并行使用asyncSeq

Asynchronous 使用BlockingQueueAgent并行使用asyncSeq,asynchronous,f#,parallel-processing,async-workflow,Asynchronous,F#,Parallel Processing,Async Workflow,是时候让我自己再尴尬一次了,因为我不了解并发在.NET中是如何工作的:p 我正在尝试编写一个函数,该函数可以封装创建一个异步工作流,该工作流接受asyncSeq输入并将其分发给n个并行使用者 let doWorkInParallel bufferSize numberOfConsumers consumer input = async { let buffer = BlockingQueueAgent<_>(bufferSize) let inputFinished

是时候让我自己再尴尬一次了,因为我不了解并发在.NET中是如何工作的:p

我正在尝试编写一个函数,该函数可以封装创建一个异步工作流,该工作流接受asyncSeq输入并将其分发给n个并行使用者

let doWorkInParallel bufferSize numberOfConsumers consumer input = async {
    let buffer = BlockingQueueAgent<_>(bufferSize)
    let inputFinished = ref false

    let produce seq = async {
        do! seq |> AsyncSeq.iterAsync (Some >> buffer.AsyncAdd)
        do! buffer.AsyncAdd None
    }

    let consumeParallel degree f = async {
        let consume f = async {
            while not <| !inputFinished do
                try
                    let! data = buffer.AsyncGet(waitTimeout)
                    match data with
                    | Some i -> do! f i
                    // whichever consumer gets the end of the input flips the inputFinished ref so they'll all stop processing
                    | None -> inputFinished := true
                with | :? TimeoutException -> ()
        }

        do! [for slot in 1 .. degree -> consume f ]
            |> Async.Parallel
            |> Async.Ignore
    }

    let startProducer = produce input
    let startConsumers = consumeParallel numberOfConsumers consumer

    return! [| startProducer; startConsumers |] |> Async.Parallel |> Async.Ignore
}

编辑:我似乎已经解决了我最初的问题(呃,我真的没有想到我在用EventWaitHandle做什么,太傻了),但我还是很想知道这是否是解决F#问题的一种完全愚蠢的方法。

我觉得我找错了方向,应该用PLINQ来代替这样的工作。或者是的,我觉得Rx不适合这样做(它是基于推的,我想要基于拉的)。我认为Parallel.Foreach()。带有degreeofparallelism()可能会为您节省很多工作,就像您在评论中添加的那样。是否可以使用Parallel.Foreach()样式支持取消?
let input = seq {1..50} |> AsyncSeq.ofSeq
let action i = async {
    do! Async.Sleep 500
    printfn "%d GET" i
    }
let test = doWorkInParallel 10 2 action input
Async.RunSynchronously test