vto*_*ola 3 recursion f# asynchronous tail-recursion idisposable
据我所知,use关键字IDisposable尽快超出范围处理绑定,所以考虑这个递归函数:
let rec AsyncAcceptMessages(client : WebSocket) =
async {
let! message = client.AsyncReadMessage
use reader = new StreamReader(message)
let s = reader.ReadToEnd()
printf "%s" <| s
do! AsyncAcceptMessages client
}
Run Code Online (Sandbox Code Playgroud)
让我们假装编译器没有找到使用尾递归的方法,是否会StreamReader 在每次递归后处理?
UPDATE
当你真正期待某些东西回来时,托马斯的反应向我展示了一种修复它的方法,但是如果你什么都没想到呢?就像在这个例子中的StreamWriter:
let rec AsyncAcceptMessages(client : WebSocket) =
async {
let! message = client.AsyncReadMessage
if(not(isNull message)) then
let s =
use reader = new StreamReader(message)
reader.ReadToEnd()
use writer = new StreamWriter(client.CreateMessageWriter(WebSocketMessageType.Text), Encoding.UTF8)
writer.Write s
printf "%s" <| s
do! AsyncAcceptMessages client
}
Run Code Online (Sandbox Code Playgroud)
正如你所说的StreamReader那样,只有在执行从递归调用返回后才会被处理掉(即从不).
还有另一个问题,即do!不被视为尾递归调用,所以如果你想创建一个无限的尾递归循环,你需要使用return!(否则你的代码会泄漏内存).
在这种情况下,您可以轻松地使用它来修复它,因为您没有使用它进行任何异步操作StreamReader,因此您只需创建一个普通的本地范围:
let rec AsyncAcceptMessages(client : WebSocket) =
async {
let! message = client.AsyncReadMessage
let s =
use reader = new StreamReader(message)
reader.ReadToEnd()
printf "%s" <| s
return! AsyncAcceptMessages client
}
Run Code Online (Sandbox Code Playgroud)
如果你想打电话给eg AsyncReadToEnd,那么你可以这样做:
let rec AsyncAcceptMessages(client : WebSocket) =
async {
let! message = client.AsyncReadMessage
let! s =
async { use reader = new StreamReader(message)
return! reader.ReadToEnd() }
printf "%s" <| s
return! AsyncAcceptMessages client
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
215 次 |
| 最近记录: |