当我调用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 }