fsprojects / FSharpx.Async

Asynchronous programming utilities for F#
http://fsprojects.github.io/FSharpx.Async/
Other
94 stars 31 forks source link

Unable to cancel AwaitObservable #58

Open Rich-F-G-Mills opened 4 months ago

Rich-F-G-Mills commented 4 months ago

Description

While AwaitObservable is awaiting the observable to produce a value/complete/error, it is not responsive to the prevailing cancellation token.

Repro steps

open System
open System.Threading
open FSharpx.Control.Observable
open FSharp.Control.Reactive

let obs =
    Observable.single 5
    |> Observable.delay (TimeSpan.FromMilliseconds 2_000)

let cts =
    new CancellationTokenSource ()

do cts.CancelAfter (TimeSpan.FromMilliseconds 1_000)

try
    ignore <| Async.RunSynchronously (Async.AwaitObservable obs, cancellationToken = cts.Token)
with exn ->
    do printfn "Exception: %s" exn.Message

Expected behavior

I would have expected an OperationCancelledException to have been raised by RunSynchronously.

Am I alone in thinking this would be expected behaviour?

Actual behavior

When running the code above, execution hangs.

From the source code, there is a line where a callback is registered on cancellation.

However, all this does is dispose of the subscription instead of passing OperationCancelledException to the ccont continuation. Not surprising given it doesn't have sight of ccont when registration is instantiated.

Known workarounds

Have come up with alternate version for my own personal project but not sure it would "cut the mustard" elsewhere.

Side-note

I've spent a number of days (bordering on an obsession) pondering just how AwaitObservable worked and it was a real masterclass in seeing what solutions are possible (issue above aside).