2012-09-20 3 views
1

얻기 취소 토큰은

let test = 
    Async.FromContinuations(
     fun (cont,econt,ccont) -> 
      let rec inner() = 
       async { 
        do printfn "looping..." 
        do! Async.Sleep 1000 
        return! inner() 
       } 

      Async.Start(inner()) 
      cont()) 

은 가정하자 나는 때문에, 이것은 자연적으로 내부 루프 정지를하지 않습니다 그래서

let cts = new CancellationTokenSource() 
Async.Start(test, cts.Token) 
cts.Cancel() 

같은 계산을 시도 할 다음과 같은 정의를 고려 적절한 해약 토큰을 통과하지 못했습니다. Async.FromContinuations를 통해 외부 취소 토큰을 얻을 수있는 방법이 있습니까? 비동기 빌더와 Async.CancellationToken을 사용하여이 코드를 다시 작성할 수 있지만, 내부 표현식에 연속성을 전달할 수있는 기능이 손실됩니다.

답변

2

이 같은 smth?

let test = 
    async { 
     let! ct = Async.CancellationToken 
     return! Async.FromContinuations(
      fun (cont,econt,ccont) -> 
       let rec inner() = 
        async { 
         do printfn "looping..." 
         do! Async.Sleep 1000 
         return! inner() 
        } 

       Async.Start(inner(), cancellationToken = ct) 
       cont()) 
    } 
let cts = new CancellationTokenSource() 
Async.Start(test, cts.Token) 
cts.CancelAfter(1000) 
+0

CTS를 폐기하는 것을 잊지 마세요. 비동기의 use 절 아래에 밀어 넣어 두는 것이 좋습니다. – t0yv0

+2

@toyvo 동의 - 누락 된 'Dispose'가 잘못되었습니다. 그러나 CTS가 발신자 (누가 그것을 만든 사람)에 의해 처리되어서는 안됩니까? 아마도'cts.Cancel()'호출 이후인가? (나는 비동기 내부에서'Dispose '를 호출하는 것이 잘못 될 수 있다고 생각할 것이다.) –

+0

@TomasPetricek 네, 맞습니다. 비동기 완료시 CTS를 해제하려는 경우를 생각했지만 Dispose 후 Cancel이 호출되지 않도록해야합니다. 그것은 더 많은 코드가 필요합니다. – t0yv0

2

무엇을하려고 하시겠습니까? 코드를 올바르게 이해하면 백그라운드에서 inner 루프 기능을 시작한 다음 병렬로 나머지 워크 플로우 (cont() 호출 사용)를 계속 실행하고 싶습니다.

이렇게하려면 Async.FromContinuations이 필요하지 않습니다. 이 정확히을 을하는 기능이며, 그것은 또한 당신이이 같은 프로그램을 다시 쓸 수 있다고 생각 처리 예외 처리, 취소 토큰 등

를 취 계산의

let test = 
    // The inner loop function from your example 
    let rec inner() = async { 
     do printfn "looping..." 
     do! Async.Sleep 1000 
     return! inner() } 

    async { 
     // Start the inner loop as a child async 
     let! _ = Async.StartChild(inner()) 
     // ... continue doing other things in parllel if you wish 
     do printfn "main body running..." } 

시작 및 취소를 등 그것을 취소 토큰을 전달하면 Async.StartChild 다음이 내부 작업을 시작합니다 let!를 사용하여 호출하는 경우

let cts = new CancellationTokenSource() 
Async.Start(test, cts.Token) 
// This will cancel the 'inner' loop as well 
cts.Cancel() 

그것은 retur : 전에 같이 보인다 ns는 나중에 자식 작업이 완료 될 때까지 기다릴 수있는 토큰이지만 그 작업을 수행하지 않으므로 _ 패턴을 사용했습니다.

+0

내부 AsyncParamsAux 형식을 사용하는 FSharp.Core의 기본 선언과 비슷한 방법으로 연속에서 워크 플로를 정의 할 때 취소 토큰을 얻는 방법을 찾고있었습니다. 그래서 내가 게시 한 내부 코드는 기본적으로 필러입니다. 비동기 {} 표현식으로 Async.FromContinuations 선언을 래핑하는 것이 그 목적에 충분할 것이라고 추측합니다. – eirik

관련 문제