等待F#中的RX主题

Joh*_*lds 5 f# system.reactive

这与我如何在不引入竞争条件的情况下等待来自RX主题的响应相同,但在F#.

C#解决方案看起来像:

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);
}
Run Code Online (Sandbox Code Playgroud)

我在F#的尝试是这样的:

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 ()
    }
Run Code Online (Sandbox Code Playgroud)

let x! = firstInt给出了编译错误This expression was expected to have type Async<'a> but here has type IConnectableObservable<int>这样显然C#这是否F#不引擎盖下的东西.

是否有一个C#隐式接口在这里工作,我需要在F#中明确地做什么?如果是这样,我无法弄清楚它是什么.

Bat*_*bix 5

经过进一步挖掘,似乎 C#GetAwaiter()在您执行某些操作时会在幕后调用await。对于 aSubject或 an IObservableGetAwaiter返回 an AsyncSubject,这在 F# 中并不立即有用,但ToTask中的扩展方法System.Reactive.Threading.Tasks使其有用。显然,您可以ToTask直接应用于 a Subject(或IObservable) 而无需通过GetAwaiter,因此我的问题通过将语句更改为以下方式解决let! x ...

    let! x = firstInt.ToTask() |> Async.AwaitTask
Run Code Online (Sandbox Code Playgroud)

编辑:

有一个更好的方法

使用FSharpx.Async是完成同样事情的更好方法:

    let! x = firstInt.ToTask() |> Async.AwaitTask
Run Code Online (Sandbox Code Playgroud)