我有一个代理,我设置它在后台做一些数据库工作。实现看起来像这样:
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 对象堆积起来而不是被释放,最终我会用完连接池中的连接(我没有关于有多少“几个”,但连续两次运行集成测试套件总是会导致连接池干涸)。
如果我将其更改use
为 a ,using
那么事情就会得到妥善处理并且我没有问题:
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
在其他计算表达式中使用可以产生相同的行为?