这与How do I await a response from an RX Subject without introducing a race condition?相同,但在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);
}
我在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 ()
}
let x! = firstInt
给出了编译错误This expression was expected to have type Async<'a> but here has type IConnectableObservable<int>
,所以显然C#做了F#没有做的事情。
这里是否有一个C#隐式接口,我需要在F#中明确地做什么?如果是这样,我无法弄清楚它是什么。
答案 0 :(得分:4)
在进一步挖掘之后,当你GetAwaiter()
时,C#似乎会调用await
。对于Subject
或IObservable
,GetAwaiter
会返回AsyncSubject
,这在F#中不会立即生效,但ToTask
中的System.Reactive.Threading.Tasks
扩展方法{1}}使它变得有用。显然,您可以直接将ToTask
应用于Subject
(或IObservable
)而无需GetAwaiter
,因此我的问题可以通过更改{{1}来解决声明:
let! x ...
编辑:
使用FSharpx.Async是完成同样事情的更好方法:
let! x = firstInt.ToTask() |> Async.AwaitTask