F# Непрерывный цикл в F#
У меня есть сервер сокетов, который должен работать в цикле приема клиентов, поэтому я обнаружил, что в функциональном программировании используется рекурсивный цикл:
let awaitConnections (wsl:WebSocketListener) =
let rec loop ()=
async {
let! ws = Async.AwaitTask (wsl.AcceptWebSocketAsync(cancellation.Token) )
printfn "Connection from %s" (ws.RemoteEndpoint.Address.ToString())
Async.Start <| awaitMessages ws
do! loop()}
loop()
И этот код вызывается следующим образом:
Async.Start <| awaitConnections listener
Учитывая, что приложение работает непрерывно, я должен вместо этого использовать итеративный подход? Ли rec
подход создает вложенные стеки выполнения?
Кроме того, я хотел бы сделать что-то после окончания цикла, например:
let awaitConnections (wsl:WebSocketListener) =
let rec loop ()=
async {
let! ws = Async.AwaitTask (wsl.AcceptWebSocketAsync(cancellation.Token) )
printfn "Connection from %s" (ws.RemoteEndpoint.Address.ToString())
Async.Start <| awaitMessages ws
do! loop()}
loop()
printf "The loop ended" // <-- this line
Но тогда он не может скомпилировать, потому что awaitConnections
тип возврата. Как я мог это сделать? Я делаю это правильно?
1 ответ
Вы, безусловно, на правильном пути! Вот простой пример, который демонстрирует, что вам нужно сделать:
// Loop that keeps running forever until an exception happens
let rec loop () = async {
do! Async.Sleep(1000)
printfn "Working"
return! loop () }
// Call the loop in a try .. finally block to run some cleanup code at the end
let main () = async {
try
do! loop ()
finally
printfn "That's it!" }
// Start the work in the background and create a cancellation token
let cts = new System.Threading.CancellationTokenSource()
Async.Start(main (), cts.Token)
// To cancel it, just call: cts.Cancel()
Несколько важных моментов:
Вы не можете запустить код после завершения бесконечного цикла (это бесконечно!), Но вы можете использовать
try .. finally
запустить какой-то код, когда блок отмененОбратите внимание, что с помощью
return!
для рекурсивного зацикливания лучше - используяdo!
создает утечки памяти.Вы можете отменить вычисления, используя токен отмены - просто передайте токен при его запуске.