F#异步处理

Dav*_*ier 2 f# asynchronous

我写了这个小小的网络监听器模拟:

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)

或者诸如此类的.

谢谢!

Ank*_*kur 5

如有疑问,请使用反射器:).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)