我写了这个小小的网络监听器模拟:
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()
)
Run Code Online (Sandbox Code Playgroud)
我不明白为什么在每个循环上没有调用Dispose?
作为一个附带问题,我正在做这一切,因为我想测试在Web服务中响应文本的正确行为.我不确定我是否应该这样做:
use s = Context.Response.OutputStream
use sw = new StreamWriter(s)
sw.Write("test")
Run Code Online (Sandbox Code Playgroud)
要么
Context.Response.Write("Test")
Context.Response.End()
Run Code Online (Sandbox Code Playgroud)
或者诸如此类的.
谢谢!
如有疑问,请使用反射器:).use关键字创建"使用"的范围,直到块的结尾.在异步工作流程中使用时,如果你对async关键字进行除糖,你会得到类似的东西:
Async.Bind(Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
(fun context ->
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")
Async.ReturnFrom ( respondOut() )
)
Run Code Online (Sandbox Code Playgroud)
现在调用Async.ReturnFrom最后将继续以递归方式调用该函数,如果用"C#using(){}"替换使用,其中}括号位于Async.ReturnFrom之后,那么dispose永远不会被调用
将使用部分包装在do块中可以解决问题:
let rec respondOut() = async {
let! context = Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
do
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()
}
Run Code Online (Sandbox Code Playgroud)