F#中的F#连续循环

vto*_*ola 9 f# asynchronous task-parallel-library f#-3.0

我有一个套接字服务器,需要在接受客户端的循环上运行,所以我发现在函数编程中,使用了一个递归循环:

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()
Run Code Online (Sandbox Code Playgroud)

通过执行以下操作调用此代码:

Async.Start <| awaitConnections listener
Run Code Online (Sandbox Code Playgroud)

考虑到应用程序连续运行,我应该使用迭代方法吗?该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
Run Code Online (Sandbox Code Playgroud)

但是后来因为awaitConnections返回类型而无法编译.我怎么能这样做?我这样做了吗?

Tom*_*cek 19

你肯定是在正确的轨道上!这是一个简单的示例,演示了您需要执行的操作:

// 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()
Run Code Online (Sandbox Code Playgroud)

一些要点:

  • 在无限循环结束后你无法真正运行代码(它是无限的!)但你可以用来try .. finally在块被取消时运行一些代码

  • 请注意,使用return!递归循环更好 - 使用do!创建内存泄漏.

  • 您可以使用取消令牌取消计算 - 只需在启动时传递令牌.

  • 谢谢!我在哪里可以找到关于`return!`与`do!`的更多信息? (3认同)
  • 这是一个有问题的问题,但我会试一试.像`async`这样的计算表达式是一系列函数调用的语法糖,返回元素是函数的结果.`do!`定义了一个返回`unit`的表达式,它(在这种情况下)基本上创建了一个新的`Async <'a>`对象,除了在一个递归调用和下一个之间做什么,`return!`避免这个.不可否认,这需要考虑一下`Async`对象如何在幕后工作以使一切都发生. (2认同)