Reputation: 35905
As far as I understood, the use
keyword disposes the bound IDisposable
as soon it is out of scope, so considering this recursive function:
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
}
Let's pretend that the compiler does not find a way of using tail recursion, would that StreamReader
be disposed after each recursion?
UPDATE
Tomas response show me a way of fixing it when you actually expect something back, but what if you are expecting nothing? like in this example with the 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
}
Upvotes: 3
Views: 303
Reputation: 243051
As you're saying, the StreamReader
would only be disposed of after the execution returns from the recursive call (i.e. never).
There is another issue, which is that do!
is not treated as a tail-recursive call, so if you want to create an infinite tail-recursive loop, you need to use return!
(otherwise your code will be leaking memory).
In this case, you can fix it easily using, because you're not doing any asynchronous operations with the StreamReader
, so you can just create an ordinary local scope:
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
}
If you wanted to call e.g. AsyncReadToEnd
, then you could do something like:
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
}
Upvotes: 5