When does f # async check its CancellationToken?

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" } 
+6
source share
1 answer

I see the same results that you have with F # 2.0 only in interactive Fsi. If I put the same code in a file and ran fsi cancel.fsx , then there will be no final after and this is what you expect.

Fsi v11 and v12 show the expected result for both ways to run the code.

This suggests that when starting Fsi v2.0 in interactive mode, there is some error or difference that was fixed in a later version of FSharp.

+1
source

All Articles