我正在读F# for fun and profit - Asynchronous programming。在取消工作流下,它们具有以下示例:

let testLoop = async {
    for i in [1..100] do
    // do something
    printf "%i before.." i

    // sleep a bit
    do! Async.Sleep 10
    printfn "..after"
    }

open System
open System.Threading

// create a cancellation source
let cancellationSource = new CancellationTokenSource()

// start the task, but this time pass in a cancellation token
Async.Start (testLoop,cancellationSource.Token)

// wait a bit
Thread.Sleep(200)

// cancel after 200ms
cancellationSource.Cancel()
关于这一点,他们说:

但是,对于我(VS2010,F#2.0,F#Interactive),我得到以下输出。请注意,在取消 token 后,它还如何打印..after。他们只是错了吗?
1 before....after
2 before....after
3 before....after
4 before....after
5 before....after
6 before....after
7 before....after
8 before....after
9 before....after
10 before....after
11 before....after
12 before....after
13 before..
val cancellationSource : CancellationTokenSource

>
..after
那么也许取消检查是在输入Async.Sleep时完成的吗?不,那么它将被打印出来:
13 before....after
14 before..
val cancellationSource : CancellationTokenSource

>
因此,似乎检查实际上在for循环中! IE。它一直运行,直到取消后的for循环为止。这是怎么运作的?如果我希望它在 sleep 后检查怎么办?
这个问题似乎暗示着取消工作,就像我上面描述的那样:Can I explicitly check for cancellation / terminate async computation?
编辑:
关于这是否仅在FSI 2.0中:如果一个 sleep 分别为200ms,2500ms和4000ms,以下循环会发生什么?它打印在中间吗?
let testLoop = async {
    for i in [1..5] do
    printf "%i before.." i
    do! Async.Sleep 2000
    printfn "..middle.."
    do! Async.Sleep 1000
    printfn "..after"
    }

最佳答案

我在交互式Fsi中只能看到与F#2.0相同的结果。如果我将相同的代码放入文件中并运行fsi cancel.fsx,则输出将没有最终的after,这就是您所期望的。

Fsi v11和v12显示了两种运行代码的预期输出。

这表明在交互式运行Fsi v2.0时存在一些错误或差异,该错误或差异已在更高版本的FSharp中修复。

关于asynchronous - f#异步何时检查其CancellationToken?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21188452/

10-10 03:50