Asynchronous F#F中的连续循环#

Asynchronous F#F中的连续循环#,asynchronous,f#,task-parallel-library,f#-3.0,Asynchronous,F#,Task Parallel Library,F# 3.0,我有一个套接字服务器,需要在接受客户端的循环上运行,因此我发现在函数编程中,使用了递归循环: let awaitConnections (wsl:WebSocketListener) = let rec loop ()= async { let! ws = Async.AwaitTask (wsl.AcceptWebSocketAsync(cancellation.Token) ) printfn "Connection

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

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()

但是它无法编译,因为
等待连接
返回类型。我怎么能这么做?我这样做对吗?

你肯定走对了路!下面是一个简单的示例,演示了您需要执行的操作:

// 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。。最后
    在取消块时运行一些代码

  • 请注意,使用
    返回对于递归循环更好-使用
    do创建内存泄漏

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


谢谢!在哪里可以找到有关
return的更多信息vs.
do?这是一个很难回答的问题,但我会试一试。像
async
这样的计算表达式是一系列函数调用的语法糖,返回元素是函数的结果<代码>做
定义了一个返回
单元的表达式,它(在本例中)基本上创建了一个新的
单元,非常有用。
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
// 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()