I'm trying to use Fsharpx' Async.AwaitObservable
inside an async workflow which is started using Async.StartWithContinuations
. For some reason, if the cancellation token used to start this workflow is canceled while it is waiting for the observable (but not during other parts of the workflow), the cancellation continuation is never called. However, if I put it inside a use! __ = Async.OnCancel (interruption)
, then the interruption function does get called. Can someone please clarify why this happens and what the best way is to do this and make sure that one of the continuation functions always gets called?
open System
open System.Reactive.Linq
open FSharp.Control.Observable
open System.Threading
[<EntryPoint>]
let main _ =
let cancellationCapability = new CancellationTokenSource()
let tick = Observable.Interval(TimeSpan.FromSeconds 1.0)
let test = async {
let! __ = Async.AwaitObservable tick
printfn "Got a thing." }
Async.StartWithContinuations(test,
(fun () -> printfn "Finished"),
(fun exn -> printfn "Error!"),
(fun exn -> printfn "Canceled!"),
cancellationCapability.Token)
Thread.Sleep 100
printfn "Cancelling..."
cancellationCapability.Cancel()
Console.ReadLine() |> ignore
0 // return an integer exit code
It seems to me as well that it's a problem in how AwaitObservable is implemented. Good luck on fixing that.
That said, one workaround that you can use on your client side code is wrapping the AwaitObservable in a Task:
async {
let! ct = Async.CancellationToken
let! __ =
Async.StartAsTask(Async.AwaitObservable tick, cancellationToken = ct)
|> Async.AwaitTask
printfn "Got a thing."
}
Not ideal, but works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With