.net 反应式扩展同步订阅

.net 反应式扩展同步订阅,.net,system.reactive,reactive-programming,.net,System.reactive,Reactive Programming,是否有人可以帮助我对IObserver进行同步订阅,以便调用方法将阻塞,直到订阅完成。 例如: 出版者 }为此,您需要使用系统.Reactive.Threading.Task: 把你的观察变成一项任务 var source = Publisher.NonBlocking() .Do( (s) => Debug.WriteLines(x), () => Debug.WriteLine("Completed") ) .LastOr

是否有人可以帮助我对IObserver进行同步订阅,以便调用方法将阻塞,直到订阅完成。 例如:

出版者


}

为此,您需要使用
系统.Reactive.Threading.Task

把你的观察变成一项任务

var source = Publisher.NonBlocking()
    .Do(
        (s) => Debug.WriteLines(x),
        ()  => Debug.WriteLine("Completed")
    )
    .LastOrDefault()
    .ToTask();
Do(…).Subscribe()
就像
Subscribe(…)
。所以
Do
只是增加了一些副作用

LastOrDefault
在其中,因为由
ToTask
创建的
任务将只等待来自源
可观察的
的第一个项目,如果没有产生任何项目,它将失败(抛出)。因此,
LastOrDefault
有效地导致
任务
等待源代码完成,不管它产生什么结果

因此,在我们完成任务后,只需等待:

task.Wait(); // blocking
或使用异步/等待:

await task; // non-blocking
编辑: Cory Nelson提出了一个极好的观点:

在最新版本的C#和Visual Studio中,您实际上可以
wait
a
IObservable
。这是一个非常酷的功能,但它的工作方式与等待
任务的方式略有不同

当您等待任务时,它会导致任务运行。如果任务的单个实例被等待多次,则该任务将只执行一次。观测值略有不同。你可以把一个可观测函数看作一个异步函数,它有多个返回值。。。每次订阅observable时,observable/函数都会执行。因此,这两段代码具有不同的含义:

等待可观察到的结果:

// Console.WriteLine will be invoked twice.
var source = Observable.Return(0).Do(Console.WriteLine);
await source; // Subscribe
await source; // Subscribe
等待通过任务观察到的结果:

// Console.WriteLine will be invoked once.
var source = Observable.Return(0).Do(Console.WriteLine);
var task = source.ToTask();
await task; // Subscribe
await task; // Just yield the task's result.
因此,本质上,等待一个可观察到的结果是这样的:

// Console.WriteLine will be invoked twice.
var source = Observable.Return(0).Do(Console.WriteLine);
await source.ToTask(); // Subscribe
await source.ToTask(); // Subscribe

但是,
await-observable
语法在Xamerin Studio中不起作用(截至撰写本文时)。如果您使用的是Xamerin Studio,我强烈建议您在最后一刻使用
ToTask
,来模拟Visual Studio的
Wait observable
语法的行为。

太棒了,不知道“.Do(…”)看起来也存在LastOrDefaultAsync()方法,所以我可以执行一个.Wait()从这里,您可以直接
等待
一个
IObservable
。它将返回序列中的最后一项。@Lukie,在使用LastOrDefaultAsync之前,您可以看看我的编辑。过早地将可观察对象转换为任务可能会对代码的可重用性产生深远的影响。也就是说,如果您在最后一刻使用LastOrDefaultAsync,这可能是您最好的选择。
// Console.WriteLine will be invoked once.
var source = Observable.Return(0).Do(Console.WriteLine);
var task = source.ToTask();
await task; // Subscribe
await task; // Just yield the task's result.
// Console.WriteLine will be invoked twice.
var source = Observable.Return(0).Do(Console.WriteLine);
await source.ToTask(); // Subscribe
await source.ToTask(); // Subscribe