创建后推送新值

时间:2013-03-23 15:36:33

标签: c# system.reactive

阅读IntroToRx网站,它不鼓励使用Subject来支持Observable.Create帮助方法。

正如我所看到的,OnNext方法只能被调用到subscribe方法中,因为它是我访问Observer对象的唯一部分。

如果我想在创建新值后推出新值,该怎么办? 我被“强迫”使用主题吗?

3 个答案:

答案 0 :(得分:4)

如果您正在探索Rx,那就去吧 - 使用主题,坚持下去,看看它们是如何工作的,发现它们的利弊,然后回到这里阅读讨论为什么主题不受欢迎的问题。

主题提供更容易的“快速引导”思路和复杂的Rx场景,而无需复制实际的源条件。

也就是说,他们将状态注入有点无形的应该是无状态的操作链,所以要小心不要依赖它们。

因此,总结一下:如果您正在尝试生成序列来测试/了解rx如何工作或如何创建查询X,请使用这些主题。如果您发现自己在查询中使用它们,那么有一种更好的方法。

编辑:意识到我错过了一些东西:

另外,你问在创作后是否还有另一种提升流事件的方法......答案是肯定的;你可以通过Create或Return或Generate声明一个流,它返回你定义的任何旧的基于IObservable的对象,它也可以暴露注入事件的方法......或者,有一个lambda可以旋转一个检查共享列表的线程被路由到返回流....我想我所说的是可能性是无穷无尽的。

在Observable上声明了十几个“创建一系列事件”方法

编辑2:

一个例子?当然,让我们使用模仿真正低效的Observable.Create Subject来拼凑一些东西:

var running = true;
var values = new ConcurrentQueue<int>();
var query = Observable.Create<int>(obs =>
{
    var body = Task.Factory.StartNew(()=>
    {
        while(running)
        {
            int nextValue;
            if(values.TryDequeue(out nextValue))
            {
                obs.OnNext(nextValue);
            }
            Thread.Yield();
        }
    });
    return Disposable.Create(() =>
    {
        try
        {
            running = false;
            body.Wait();
            obs.OnCompleted();            
        }
        catch(Exception ex)
        {
            obs.OnError(ex);
        }
    });
});
using(query.Subscribe(Console.WriteLine))
{
    values.Enqueue(1);
    values.Enqueue(2);
    values.Enqueue(3);
    values.Enqueue(4);
    Console.ReadLine();
}

请注意,这只是一个快速而极其肮脏的示例代码。 :)

答案 1 :(得分:0)

这取决于你想要做什么。主题有一些案例,但是当他们第一次开始使用Rx时,并没有多少人认为。

新数据将如何输入您的序列?它会来自另一个事件吗?也许来自通信框架的消息?也许轮询一个文件?

根据这些答案,您通常会发现您已经拥有某种事件源,并且您只是从另一种模式转换为Rx(事件,轮询,回调等...)

您也不必只使用Observable.Create。您可以使用Observable.Timer / Interval设置轮询序列,使用Observable.FromEventPattern来利用现有的Event,Observable.Start进行一次性异步任务样式计算等...

由于Rx(甚至Linq)可能非常抽象,因此提出抽象问题通常可以得出非常广泛的答案。如果您指出了您正试图解决的问题,这可能有助于为您提供更好的答案。

答案 2 :(得分:0)

如果您从外部设备接收数据,则无意向IObserver.OnError发送错误信号(您认为您的信息流是无穷无尽的/和/或任何通信问题都在信息本身内),您以某种速度进行轮询,Subject的唯一问题是你可能会在任何人订阅之前开始轮询这个设备(但是增加的好处是处理你的状态非常明显,你创建了一个对象,它打开了COM端口,它通信和发布值)

使用Observable.CreateObservable.Timer/Interval可能会更好 - 但懒惰是主要原因,无论如何你都会管理状态。您可能需要使用Publish()。RefCount()来阻止第二个订阅打开端口。