I read F # for fun and profit - asynchronous programming . In the Cancel Workflows section, they have the following example:
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()
They say about this:
In F #, any nested asynchronous call will automatically check for the cancel token!
In this case, it was a line:
do! Async.Sleep(10)
As you can see in the output, cancellation occurs on this line.
However, for me (VS2010, F # 2.0, F # Interactive) I get the following output. Notice how it also prints ..after after I canceled the token. Are they just wrong?
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
So, perhaps a cancellation check is performed when Async.Sleep entered? No, then he printed:
13 before....after 14 before.. val cancellationSource : CancellationTokenSource >
So it looks like validation is indeed in a for-loop! That is, it continues to work until the for loop after canceling. Does this work? What then, if I would prefer him to check after sleep?
This question seems to hint at canceling work as described above: Can I explicitly check for cancellation / termination for asynchronous computing?
Edit: As for if it is only in FSI 2.0: what happens with the next cycle if you sleep 200 ms, 2500 ms and 4000 ms respectively? Does it print average?
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" }