簡體   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