AsyncSeq.cache中的SynchronizationLockException

时间:2015-08-19 11:42:47

标签: .net f# async-await

当我调用AsyncSeq.cache时,我在调用Monitor.Exit(iref)的行中得到SynchronizationLockException。谁能说出问题是什么?

请注意我在其他项目中使用AsyncSeq.cache时没有出现此类问题。

谢谢!

见下面我的测试代码:

[<EntryPoint>]
let main argv = 
    let asyncOp x =
        async {
            do! Async.Sleep x
            return x
        }

    let chooser x = if x > 1000 then Some x else None

    let execute (input : AsyncSeq<int>) =
        async {
            printfn "First result... Expect 3s sleep"
            let! r1 = AsyncSeq.tryPick chooser input
            printfn "Computing second result. Expect no sleep"
            let! r2 = AsyncSeq.tryPick chooser input
            printfn "Done"
            return (r1,r2)
        }

    printfn "Starting..."

    let v =
        [1000;2000;3000;300000]
        |> AsyncSeq.ofSeq
        |> AsyncSeq.mapAsync asyncOp
        |> AsyncSeq.cache
        |> execute
        |> Async.RunSynchronously


    printfn "results: = %A" v
    do System.Console.ReadKey() |> ignore
    0

请参阅下面的AsyncSeq.cache代码以供参考

let cache (source : AsyncSeq<'T>) = 
    let cache = ResizeArray<_>()
    asyncSeq {
        use ie = source.GetEnumerator() 
        let iRef = ref 0
        let fin = ref false
        while not fin.Value do
            let i = iRef.Value
            lock(iRef)
            let lockTaken = ref false
            try 
                System.Threading.Monitor.Enter(iRef, lockTaken);
                if i >= cache.Count then 
                    let! move = ie.MoveNext()
                    cache.Add(move)
                    iRef := i + 1
            finally
                if lockTaken.Value then
                    System.Threading.Monitor.Exit(iRef)
            match cache.[i] with 
            | Some v -> yield v
            | None -> fin := true }

0 个答案:

没有答案