let rec loop -6ren">
gpt4 book ai didi

asynchronous - 为什么在异步计算表达式中使用 "use"绑定(bind)时资源的处理会延迟?

转载 作者:行者123 更新时间:2023-12-04 02:51:14 24 4
gpt4 key购买 nike

我有一个代理,我设置它在后台做一些数据库工作。实现看起来像这样:

let myAgent = MailboxProcessor<AgentData>.Start(fun inbox ->
let rec loop =
async {
let! data = inbox.Receive()
use conn = new System.Data.SqlClient.SqlConnection("...")
data |> List.map (fun e -> // Some transforms)
|> List.sortBy (fun (_,_,t,_,_) -> t)
|> List.iter (fun (a,b,c,d,e) ->
try
... // Do the database work
with e -> Log.error "Yikes")
return! loop
}
loop)

有了这个,我发现如果在一段时间内多次调用它,我会开始让 SqlConnection 对象堆积起来而不是被释放,最终我会用完连接池中的连接(我没有关于有多少“几个”,但连续两次运行集成测试套件总是会导致连接池干涸)。

如果我更改 useusing然后事情被妥善处理,我没有问题:
let myAgent = MailboxProcessor<AgentData>.Start(fun inbox ->
let rec loop =
async {
let! data = inbox.Receive()
using (new System.Data.SqlClient.SqlConnection("...")) <| fun conn ->
data |> List.map (fun e -> // Some transforms)
|> List.sortBy (fun (_,_,t,_,_) -> t)
|> List.iter (fun (a,b,c,d,e) ->
try
... // Do the database work
with e -> Log.error "Yikes")
return! loop
}
loop)

似乎 Using AsyncBuilder 的方法由于某种原因没有正确调用它的 finally 函数,但目前尚不清楚为什么。这是否与我编写递归异步表达式的方式有关,或者这是一些晦涩的错误?这是否表明使用 use在其他计算表达式中可以产生相同的行为吗?

最佳答案

这实际上是预期的行为 - 虽然并不完全明显!
use当异步工作流的执行离开当前范围时,构造处置资源。这与 use 的行为相同。在异步工作流之外。问题是递归调用(异步之外)或使用 return! 的递归调用(在异步内)并不意味着您要离开范围。所以在这种情况下,资源只有在递归调用返回后才会被处理掉。

为了测试这一点,我将使用一个在处理时打印的助手:

let tester () = 
{ new System.IDisposable with
member x.Dispose() = printfn "bye" }

以下函数在 10 次迭代后终止递归。这意味着只有在整个工作流程完成后,它才会继续分配资源并处理所有资源:
let rec loop(n) = async { 
if n < 10 then
use t = tester()
do! Async.Sleep(1000)
return! loop(n+1) }

如果你运行它,它将运行 10 秒,然后打印 10 次“再见”——这是因为在递归调用期间分配的资源仍在范围内。

在您的示例中, using函数更明确地界定范围。但是,您可以使用嵌套的异步工作流来执行相同的操作。以下仅在调用 Sleep 时具有范围内的资源方法,因此它在递归调用之前处理它:
let rec loop(n) = async { 
if n < 10 then
do! async {
use t = tester()
do! Async.Sleep(1000) }
return! loop(n+1) }

同样,当您使用 for循环或其他限制范围的构造,资源会立即被释放:
let rec loop(n) = async { 
for i in 0 .. 10 do
use t = tester()
do! Async.Sleep(1000) }

关于asynchronous - 为什么在异步计算表达式中使用 "use"绑定(bind)时资源的处理会延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22672966/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com