Reputation: 708
Consider the following definition
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 ())
Suppose I want to try the computation like so
let cts = new CancellationTokenSource ()
Async.Start(test, cts.Token)
cts.Cancel()
This will naturally not make the inner loop stop, since I have not passed the suitable cancellation token. Is there any way I can obtain the outer cancellation token through Async.FromContinuations? I could rewrite this using the async builder and Async.CancellationToken, but then I would lose the ability to pass continuations to the inner expression.
Upvotes: 1
Views: 459
Reputation: 243116
Can you describe what are you trying to do? If I understand your code correctly, you want to start the inner
loop function in the background and then, in parallel, continue running the rest of the workflow (using the cont()
call).
To do this, you do not need Async.FromContinuations
. There is a function that does exactly this and it also takes care of handling exceptions, cancellation tokens etc.
I think you could rewrite your program like this:
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..." }
Starting and cancelling of the computation looks as before:
let cts = new CancellationTokenSource ()
Async.Start(test, cts.Token)
// This will cancel the 'inner' loop as well
cts.Cancel()
If you call Async.StartChild
using let!
then it will start the inner task, pass it the cancellation token etc. It returns a token that you can use later to wait until the child task completes, but since you're not doing that, I used the _
pattern.
Upvotes: 3
Reputation: 16782
smth like this?
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)
Upvotes: 2