2014-11-03 4 views
7

나는 클라이언트를 받아들이는 루프에서 실행하는 데 필요한 소켓 서버를 가지고, 그래서 나는 funcional 프로그래밍, 재귀 루프를 사용하는 것을 발견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 반환 형식 때문이다. 내가 어떻게 할 수 있니? 이 일을 제대로하고 있습니까?

답변

17

당신은 확실히 바른 길입니다!

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

몇 가지 중요한 포인트 :

  • 당신은 정말 무한 루프가 완료된 후 코드를 실행 (이 무한하다!)하지만 할 수없는 다음은 간단한 예를 들어 당신이해야 할 일을 보여줍니다 즉 do!는 메모리 누수를 만들어 사용 - 블록이 재귀 루프에 대한 return!을 사용하는 것이 낫다는 것을

  • 참고 취소 될 때 몇 가지 코드를 실행하는 try .. finally를 사용할 수 있습니다.

  • 취소 토큰을 사용하여 계산을 취소 할 수 있습니다. 취소 토큰을 사용하여 계산을 취소 할 수 있습니다. 시작시 토큰 만 전달하면됩니다.

+3

고마워요! 'return!'과'do!'에 대한 더 자세한 정보는 어디에서 찾을 수 있습니까? – vtortola

+1

그건로드 된 질문이지만, 나는 그것을 줄 것이다. 'async'와 같은 계산 표현식은 일련의 함수 호출에 대한 구문적인 설탕이며, return 요소는 함수의 결과입니다. 'do!'는'unit'을 반환하는 표현식을 정의합니다.이 경우 (기본적으로) 새로운 'Async <'a>'객체가 하나만 생성되고 하나의 재귀 호출과 그 다음에 'return! 시피, 모든 것이 이루어 지도록하기 위해 비동기 객체가 장면 뒤에서 어떻게 작동하는지에 대한 생각이 필요합니다. –

+0

감사합니다. 매우 유용합니다. – vtortola