Waiting for an RX object in F #

This is the same as How to wait for a response from an RX object without introducing a race condition? but in F #.

The C # solution is as follows:

static async void Foo() { var subject = new Subject<int>(); var firstInt = subject.FirstAsync().PublishLast(); firstInt.Connect(); subject.OnNext(42); var x = await firstInt; Console.WriteLine("Done waiting: " + x); } 

My attempt in F # is as follows:

 let foo () = async { use subject = new Subject<int>() let firstInt = subject.FirstAsync().PublishLast() firstInt.Connect() |> ignore subject.OnNext(42) let! x = firstInt printfn "Done waiting: %d" x return () } 

let x! = firstInt let x! = firstInt gives a compilation error This expression was expected to have type Async<'a> but here has type IConnectableObservable<int> , so, apparently, C # does something under the hood that F # does not.

Is there a hidden C # interface when working here, what do I need to do explicitly in F #? If so, I cannot understand what it is.

+5
source share
1 answer

After further digging, it seems that C # calls GetAwaiter() under the hood when you await something. For Subject or IObservable , GetAwaiter returns AsyncSubject , which is not immediately useful in F #, but the ToTask extension ToTask in System.Reactive.Threading.Tasks makes it useful. Apparently, you can apply ToTask directly to a Subject (or IObservable ) without going through the GetAwaiter , so my problem is solved by modifying the let! x ... let! x ... to:

  let! x = firstInt.ToTask() |> Async.AwaitTask 

edit:

There is a better way

Using FSharpx.Async is a much better way to accomplish the same thing:

 open FSharpx.Control.Observable let foo () = async { use subject = new Subject<int>() subject.OnNext(42) let! x = Async.AwaitObservable subject printfn "Done waiting: %d" x return () } 
+4
source

Source: https://habr.com/ru/post/1240581/


All Articles