据我所知,use
关键字一旦超出范围就会处理绑定(bind)的 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
}
假设编译器没有找到使用尾递归的方法,StreamReader
会在每次递归后被释放吗?
更新
Tomas 的回复向我展示了一种在您实际期望得到返回时修复它的方法,但是如果您什么都不期望怎么办?就像这个使用 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
}
最佳答案
如您所说,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
}
如果您想调用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
}
关于asynchronous - F# 使用关键字和递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26976175/