【问题标题】:How does IDisposable work with use and return?IDisposable 如何处理使用和退货?
【发布时间】:2019-05-24 19:04:42
【问题描述】:

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

但是usereturn 是如何交互的呢?

例如,给定以下代码:

let createResource = async {
  use r = Resource ()

  do! operationThatMightThrow r

  return r
}

async {
  use! r = createResource

  printfn "%O" r
}
|> Async.RunSynchronously

Resource.Dispose 的调用会发生在哪里?

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

【问题讨论】:

    标签: asynchronous f# disposable


    【解决方案1】:

    我通常有两种解决方案。

    第一种方案是主动捕获异常,手动dispos一次性对象,重新抛出异常:

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

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

    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)
        ...
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2014-06-29
        • 2019-11-09
        • 1970-01-01
        • 1970-01-01
        • 2016-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-19
        相关资源
        最近更新 更多