2012-09-20 61 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

不適合這樣嗎?

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,可能是通過將它放在異步中的使用條款下。 – 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..." } 

啓動和取消看起來前:

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

如果你打電話Async.StartChild使用let!那麼它將啓動內部的任務,它傳遞取消標記等。retur ns一個令牌,稍後您可以使用它來等待子任務完成,但由於您沒有這樣做,我使用了_模式。

+0

我一直在尋找一種方法來獲得取消標記,當從continuations中定義工作流時,採用類似於使用內部AsyncParamsAux類型的FSharp.Core中的原始聲明的方式。所以我在帖子中給出的內部代碼基本上只是填充。我想包裝一個Async.FromContinuations聲明到一個異步{}表達式就足夠了。 – eirik