Asynchronous IDisposable如何使用和返回?

Asynchronous IDisposable如何使用和返回?,asynchronous,f#,disposable,Asynchronous,F#,Disposable,在F#async工作流中,我们可以定义一个应该使用use关键字清理的资源 但是use如何与return交互 例如,给定以下代码: let createResource = async { use r = Resource () do! operationThatMightThrow r return r } async { use! r = createResource printfn "%O" r } |> Async.RunSynchronously 对R

在F#
async
工作流中,我们可以定义一个应该使用
use
关键字清理的资源

但是
use
如何与
return
交互

例如,给定以下代码:

let createResource = async {
  use r = Resource ()

  do! operationThatMightThrow r

  return r
}

async {
  use! r = createResource

  printfn "%O" r
}
|> Async.RunSynchronously
Resource.Dispose
的调用将在哪里发生


我如何设计它,使
r
始终被清除(即使
操作可能抛出
抛出)?

它们将在值从计算表达式返回之前发生,语义上它们将发生在
finally
块中。如果要查看生成的using语句的源代码,可以找到它。它有效地生成了一个访问控制的dispose函数,该函数对传入的资源调用
dispose()
,然后在finally子句中使用该函数进行异步try finally阻塞。

我通常有两种解决方案

第一种解决方案是主动捕获异常,手动处理一次性对象,然后重新抛出异常:

let createResource = async {
    let r = new Resource ()
    try do! operationThatMightThrow r
    with e -> (r :> IDisposable).Dispose(); raise e
    return r
}
第二种解决方案是使用一个continuation函数,该函数将在异步返回之前访问一次性对象:

let createResource cont = async {
    use r = new Resource ()
    do! operationThatMightThrow r
    return cont r
}

async {
    let! x = createResource (fun r -> printfn "in cont: %O" r)
    ...
}