繁体   English   中英

F#异步处理

[英]F# Async Dispose

我写了这个小的Web侦听器模拟:

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?

作为一个附带的问题,我正在做所有这一切,因为我想测试什么是响应Web服务中文本的正确行为。 我不确定是否应该这样做:

use s = Context.Response.OutputStream
use sw = new StreamWriter(s)
    sw.Write("test")

要么

Context.Response.Write("Test")
Context.Response.End()

还是什么。

谢谢!

如有疑问,请使用反射器:)。 use关键字创建“ using”的作用域,直到该块结束为止。 在异步工作流程中使用时,如果对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() )
                )

现在,最后调用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()
            }

use扩展到块的末尾,因此我希望在递归计算返回之后调用Dispose (在这种情况下,因为它是无条件循环的,所以永远不会调用)。 如果您想更早地处置资源,则需要以某种方式界定use绑定的范围。 也许像这样的事情会工作(我还没有尝试过):

let rec respondOut() = async {
    let! context = Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
    do! async {
        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()
}

我的猜测是,由于未使用disp已在您的编译代码中对其进行了优化。 尝试在下一行添加printfn "%A" disp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM