为什么不受试者在.NET中无扩展推荐? [英] Why are Subjects not recommended in .NET Reactive Extensions?

查看:99
本文介绍了为什么不受试者在.NET中无扩展推荐?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前得到认真处理的。NET的反应扩展的框架,我通过各种资源的引进工作我的方式,我发现(主要是 http://www.introtorx.com

I am currently getting to grips with the Reactive Extensions framework for .NET and I am working my way through the various introduction resources I've found (mainly http://www.introtorx.com)

我们的应用涉及了若干检测网络帧的硬件接口,这些都将是我的IObservables,那么我有各种各样的,将消耗这些帧或执行上的数据变换的某种方式组件,并产生一个新的帧的类型。也将有需要显示例如每第n帧等组成。
我深信,接收将是我们的应用程序非常有用,但我对实施细节IObserver接口挣扎。

Our application involves a number of hardware interfaces that detect network frames, these will be my IObservables, I then have a variety of components that will consume those frames or perform some manner of transform on the data and produce a new type of frame. There will also be other components that need to display every n'th frame for example. I am convinced that Rx is going to be useful for our application, however I am struggling with the implementation details for the IObserver interface.

大部分(如果不是全部)我一直在阅读资源的说,我不应该实施的IObservable接口自己,但使用所提供的函数或类之一。
从我的研究看来,创建一个受试对象; IBaseFrame> 将提供我我需要什么,我有我的单线程,从硬件接口读取数据,然后调用OnNext我的的功能受试对象; IBaseFrame> 实例。然后,不同IObserver组件会从主题接受他们的通知。

Most (if not all) of the resources I have been reading have said that I should not implement the IObservable interface myself but use one of the provided functions or classes. From my research it appears that creating a Subject<IBaseFrame> would provide me what I need, I would have my single thread that reads data from the hardware interface and then calls the OnNext function of my Subject<IBaseFrame> instance. The different IObserver components would then receive their notifications from that Subject.

我的困惑是从未来的建议给这个教程,它说:

My confusion is coming from the advice give in the appendix of this tutorial where it says:

避免使用对象类型。 RX是一个有效的函数式编程范式。使用对象意味着我们现在管理的状态,这是潜在的变异。在同一时间两个变异状态和异步编程打交道是很难得到的权利。此外,许多运营商(扩展方法)都被浓墨重彩地确保订阅和保持序列指出坚持正确的寿命;当你介绍对象,你可以打破这一点。未来版本还可以看到显著的性能下降,如果你明确地使用主题。

Avoid the use of the subject types. Rx is effectively a functional programming paradigm. Using subjects means we are now managing state, which is potentially mutating. Dealing with both mutating state and asynchronous programming at the same time is very hard to get right. Furthermore, many of the operators (extension methods) have been carefully written to ensure that correct and consistent lifetime of subscriptions and sequences is maintained; when you introduce subjects, you can break this. Future releases may also see significant performance degradation if you explicitly use subjects.

我的应用程序是相当性能的关键,我显然会它会在生产code之前测试用接收模式的性能;然而,我很担心,我做的东西是对接收框架的精神,通过主题类和框架的未来版本将损害性能。

My application is quite performance critical, I am obviously going to test the performance of using the Rx patterns before it goes in to production code; however I am worried that I am doing something that is against the spirit of the Rx framework by using the Subject class and that a future version of the framework is going to hurt performance.

有没有这样做我想要什么更好的办法?硬件轮询线程将被连续运行是否有任何观察员或没有(硬件缓冲区将备份其他方式),所以这是一个非常热的序列。我需要再通过接收到的帧到多个观察员。

Is there a better way of doing what I want? The hardware polling thread is going to be running continuously whether there are any observers or not (the HW buffer will back up otherwise), so this is a very hot sequence. I need to then pass the received frames out to multiple observers.

任何意见将是极大的AP preciated。

Any advice would be greatly appreciated.

推荐答案

好吧,
如果我们忽略我的教条的方式,而忽略科目都好/坏在一起。让我们来看看这个问题的空间。

Ok, If we ignore my dogmatic ways and ignore "subjects are good/bad" all together. Let us look at the problem space.

我敢打赌,你要么有1 2风格的系统,你需要为忘恩

I bet you either have 1 of 2 styles of system you need to ingrate to.


  1. 系统将引发一个事件或者一个电话回来时,一个消息到达

  2. 您需要轮询系统,看看是否有任何消息处理

有关选项1,容易,我们只是用适当的方法FromEvent包裹它,我们正在做。去酒吧!

For option 1, easy, we just wrap it with the appropriate FromEvent method and we are done. To the Pub!

有关选项2,我们现在需要考虑如何查询此,如何有效牙缝做到这一点。此外,当我们得到的价值,我们怎么发布呢?

For option 2, we now need to consider how we poll this and how to do this effciently. Also when we get the value, how do we publish it?

我会想象你想轮询专用线程。你不希望其他一些codeR锤击线程池/ TaskPool并留下你在一个线程池饥饿的情况。或者你不想上下文切换的麻烦(我猜)。因此,假设我们有我们自己的线程,我们可能有某种虽然/睡眠循环,我们坐在轮询。当检查发现的一些消息,我们发布。那么这一切听起来很完美的Observable.Create。现在,我们可能不能使用whil​​e循环,这不会让我们永远返回一次性允许取消。幸运的是,您已经阅读整本书等等都是精明的递归调度!

I would imagine that you would want a dedicated thread for polling. You wouldn't want some other coder hammering the ThreadPool/TaskPool and leaving you in a ThreadPool starvation situation. Alternatively you don't want the hassle of context switching (I guess). So assume we have our own thread, we will probably have some sort of While/Sleep loop that we sit in to poll. When the check finds some messages we publish them. Well all of this sounds perfect for Observable.Create. Now we probably cant use a While loop as that wont allow us to ever return a Disposable to allow cancellation. Luckily you have read the whole book so are savvy with Recursive scheduling!

我想象这样的事情会工作。 #NotTested

I imagine something like this could work. #NotTested

public class MessageListener
{
    private readonly IObservable<IMessage> _messages;
    private readonly IScheduler _scheduler;

    public MessageListener()
    {
        _scheduler = new EventLoopScheduler();

        var messages = ListenToMessages()
                                    .SubscribeOn(_scheduler)
                                    .Publish();

        _messages = messages;
        messages.Connect();
    }

    public IObservable<IMessage> Messages
    {
        get {return _messages;}
    }

    private IObservable<IMessage> ListenToMessages()
    {
        return Observable.Create<IMessage>(o=>
        {
                return _scheduler.Schedule(recurse=>
                {
                    try
                    {           
                        var messages = GetMessages();
                        foreach (var msg in messages)
                        {
                            o.OnNext(msg);
                        }   
                        recurse();
                    }
                    catch (Exception ex)
                    {
                        o.OnError(ex);
                    }                   
                });
        });
    }

    private IEnumerable<IMessage> GetMessages()
    {
         //Do some work here that gets messages from a queue, 
         // file system, database or other system that cant push 
         // new data at us.
         // 
         //This may return an empty result when no new data is found.
    }
}

我真的不喜欢的科目究其原因,是通常不是真的有对问题的明确的设计开发人员的情况。哈克在一个主题,在这里捅它四处奔走,然后让在WTF穷人去支持开发猜是怎么回事。当您使用创建/生成等方法要本地化对序列的影响。你可以看到这一切在一个方法,你知道没有其他人在一个讨厌的副作用扔。如果我看到一个学科领域我现在必须去寻找都在一个班正在使用它的地方。如果某些MFER暴露一个公开,则全盘皆输,谁知道是如何被使用该序列!
异步/并发/接收是很难的。你不需要通过允许副作用和因果关系编程更加旋转你的头,使其更难。

The reason I really don't like Subjects, is that is usually a case of the developer not really having a clear design on the problem. Hack in a subject, poke it here there and everywhere, and then let the poor support dev guess at WTF was going on. When you use the Create/Generate etc methods you are localizing the effects on the sequence. You can see it all in one method and you know no-one else is throwing in a nasty side effect. If I see a subject fields I now have to go looking for all the places in a class it is being used. If some MFer exposes one publicly, then all bets are off, who knows how this sequence is being used! Async/Concurrency/Rx is hard. You don't need to make it harder by allowing side effects and causality programming to spin your head even more.

这篇关于为什么不受试者在.NET中无扩展推荐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆