F # Async Dispose - PullRequest
       3

F # Async Dispose

2 голосов
/ 15 сентября 2011

Я написал эту маленькую симуляцию веб-слушателя:

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()
    )

Я не понимаю, почему Dispose не вызывается по disp на каждом цикле?

В качестве дополнительного вопроса я делаю все это, потому что хочу проверить, как правильно реагировать на текст в веб-сервисе. Я не уверен, что мне следует делать:

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

или

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

или еще много чего.

Спасибо!

Ответы [ 3 ]

5 голосов
/ 15 сентября 2011

Если есть сомнения, используйте отражатель :). Ключевое слово use создает область действия «using» до конца блока. При использовании внутри асинхронного рабочего процесса, если вы удалите сахар из асинхронного ключевого слова, вы получите что-то вроде:

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, тогда удаление никогда не будет вызвано

Оборачивание используемой части в блок 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()
            }
2 голосов
/ 15 сентября 2011

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()
}
0 голосов
/ 15 сентября 2011

Я думаю, disp оптимизировано в вашем скомпилированном коде, так как оно не используется. Попробуйте добавить printfn "%A" disp на следующей строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...