2014-11-03 11 views
7

Ben istemcileri kabul eden bir döngü çalıştırmak için gereken bir soket sunucusu var, bu yüzden funcional programlamada, bir özyinelemeli döngü kullanılır öğrendim:F # Sürekli döngü

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

Ve bu kod çağrılır yaparak:

Async.Start <| awaitConnections listener 

, uygulama kesintisiz olarak çalışmasını göz önüne alındığında bunun yerine bir iteratif yaklaşım kullanmak gerekir? rec yaklaşımı iç içe yürütme yığınları oluşturur mu?

Ayrıca, ben gibi, döngü sona erdikten sonra bir şey yapmak istiyorum:

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 

Ama sonra derleme olamaz awaitConnections dönüş türü nedeniyle. Bunu nasıl yapabilirim? Bunu doğru mu yapıyorum?

cevap

17

Kesinlikle doğru yoldasınız!

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

birkaç önemli noktalar:

  • Gerçekten sonsuz döngü tamamlandıktan sonra kod çalıştırmasına (o sonsuzdur!) Ama olamaz İşte basit bir örnek yapmanız gerekenler kanıtlaması do! bellek sızıntılarını oluşturur kullanarak - blok özyinelemeli döngü için return! kullanarak daha iyi olduğunu

  • Not iptal edildiğinde bazı kodlar çalıştırmak için try .. finally kullanabilirsiniz.

  • Hesaplama işlemini iptal jetonunu kullanarak iptal edebilirsiniz - başlatırken yalnızca simgeyi geçirmeniz yeterlidir.

+3

Teşekkürler! 'return!' vs. 'do!' hakkında daha fazla bilgiyi nerede bulabilirim? – vtortola

+1

Yüklü bir soru, ama ona bir şans vereceğim. "Async" gibi hesaplama ifadeleri, bir dizi işlev çağrısı için sözdizimsel şekerdir ve dönüş elemanı işlevlerin sonucudur. '' '' '' '' '' 'döndüren bir ifadeyi tanımlar, ki bu durumda (bu durumda) temel olarak yeni bir' Async <'a> 'nesnesi yaratır; bu, hiçbir şey yapmaz, ancak bir tekrarlı çağrı ile bir sonraki“ geri dönüş ”arasında gidip gelir, bunu engeller. Kuşkusuz bu, Async'in nesnelerinin her şeyin gerçekleşmesi için sahnelerin arkasında nasıl çalıştığı hakkında biraz düşünür. –

+0

Teşekkürler, çok yardımcı. – vtortola