IDisposable 如何使用和返回?

sdg*_*sdh 5 f# asynchronous 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
Run Code Online (Sandbox Code Playgroud)

呼叫将在哪里Resource.Dispose发生?

我该如何设计以便r始终清理(即使operationThatMightThrow抛出)?

Ngh*_*Bui 2

我通常有两种解决方案。

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

let createResource = async {
    let r = new Resource ()
    try do! operationThatMightThrow r
    with e -> (r :> IDisposable).Dispose(); raise e
    return r
}
Run Code Online (Sandbox Code Playgroud)

第二种解决方案是使用延续函数,该函数可以在异步返回之前访问一次性对象:

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