F# 异步处置
我写了这个小的网络侦听器模拟:
Agent.Start(fun (_ : MailboxProcessor<unit>) ->
let listener = new HttpListener()
listener.Prefixes.Add(addr)
listener.Start()
let rec respondOut() = async {
let! context = Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
use s = context.Response.OutputStream
let wr = new StreamWriter(s)
use disp = { new IDisposable with
member x.Dispose() =
printfn "Disposing..."
wr.Dispose() }
wr.Write("Test")
return! respondOut()
}
respondOut()
)
我不明白为什么在每个循环的 disp 上不调用 Dispose?
作为一个附带问题,我这样做是因为我想测试在网络服务中响应文本的正确行为是什么。我不确定我是否应该做:
use s = Context.Response.OutputStream
use sw = new StreamWriter(s)
sw.Write("test")
或者
Context.Response.Write("Test")
Context.Response.End()
或者诸如此类的事情。
谢谢!
I wrote this little web listener simulation:
Agent.Start(fun (_ : MailboxProcessor<unit>) ->
let listener = new HttpListener()
listener.Prefixes.Add(addr)
listener.Start()
let rec respondOut() = async {
let! context = Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
use s = context.Response.OutputStream
let wr = new StreamWriter(s)
use disp = { new IDisposable with
member x.Dispose() =
printfn "Disposing..."
wr.Dispose() }
wr.Write("Test")
return! respondOut()
}
respondOut()
)
I don't understand why Dispose is not called on disp on every loop?
As a side question, I'm doing all this because I want to test what is the proper behavior to respond text in a web service. I'm not sure if I should be doing:
use s = Context.Response.OutputStream
use sw = new StreamWriter(s)
sw.Write("test")
or
Context.Response.Write("Test")
Context.Response.End()
or whatnot.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如有疑问,请使用反射器:)。 use 关键字创建“using”的范围,直到块结束。在异步工作流程中使用时,如果对 async 关键字进行脱糖处理,您将得到类似以下内容:
现在,调用 Async.ReturnFrom 最后将继续递归调用该函数,并且如果您将 use 替换为“ C# using() { } ”,其中} 括号位于 Async.ReturnFrom 之后,则永远不会调用 dispose
将 use 部分包装在 do 块中应该可以解决问题:
When in doubt, use reflector :). The use keyword create the scope of "using" till then end of the block. When used inside the async workflow if you de-sugar the async keyword you will get something like:
Now the call Async.ReturnFrom at last will continue calling the function recursively and if you replace the use with " C# using() { } " where the } bracket is after the Async.ReturnFrom then the dispose will never get called
Wrapping the use part in a do block should solve the problem:
use
扩展到块的末尾,因此我希望Dispose
在递归计算返回之后被调用(在这个例子中,从来没有)情况,因为它无条件循环)。如果您想提前处理资源,则需要以某种方式界定use
绑定的范围。也许这样的事情会起作用(我还没有尝试过):use
extends to the end of the block, so I would expectDispose
to be called after the recursive computation returns (which is never, in this case, since it loops unconditionally). If you want to dispose of the resource earlier, you'll need to delimit the scope of theuse
binding somehow. Perhaps something like this would work (I haven't tried it):我的猜测是
disp
在编译的代码中被优化掉了,因为它没有被使用。尝试在下一行添加printfn "%A" disp
。My guess is
disp
is optimized away in your compiled code since it isn't used. Try addingprintfn "%A" disp
on the next line.