Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fsharpx Async.AwaitObservable does not call cancellation continuation

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
like image 685
Anton Tcholakov Avatar asked Sep 28 '22 21:09

Anton Tcholakov


1 Answers

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.

like image 128
scrwtp Avatar answered Oct 05 '22 13:10

scrwtp