如何实现IObservable <t>多线程?</t>

时间:2011-01-28 01:25:48

标签: c# multithreading asynchronous system.reactive

我根据[Rx DEVHOL202]和http://rxwiki.wikidot.com/101samples#toc48

中的示例编写了一个实现

这是我的代码。 http://csharp.pastebin.com/pm2NAPx6

  1. 它可以工作,但对OnNext的调用不是NonBlocking,这是我想要实现的模拟网络读取和异步处理每个字节块,因为它被读取到处理程序[不是这里显示完整但可能会缓存结果并进行进一步处理]。

    这样做的好方法是什么?

  2. 抛出异常后,所有后续的OnNext()都不会被处理!! 如果我没有明确退出循环并指示完成。 为什么会这样?

2 个答案:

答案 0 :(得分:2)

我强烈建议反对尝试实施您自己的IObservable。隐式规则超出了线程安全性和方法调用顺序。

通常你会从方法中返回IObservable个实例,但是如果你需要一个直接实现它的类,你应该包装一个Subject

public class SomeObservable<T> : IObservable<T>
{
        private Subject<T> subject = new Subject<T>();

        public IDisposable Subscribe(IObserver<T> observer)
        {
            return subject.Subscribe(observer);
        }
}

1。您需要注意观察者如何支持这一点(因为您可能有共享数据),但您可以通过以下两种方式之一异步处理调用:

  • 在致电ObserveOn(Scheduler.TaskPool)之前,请致电ThreadPool(如果您是4.0之前,请Subscribe)。这会导致消息通过调度程序(在本例中为任务)进行路由
  • IScheduler传递给Observer构造函数
  • 从订阅者处启动异步任务/线程

2。这是预期的功能。 IObservableIObserver之间的合同是(OnNext)* (OnCompleted | OnError)?,也就是说“对OnNext进行零次或多次调用,可选地后跟EITHER OnCompleted或OnError”。在OnCompleted|OnError之后,调用OnNext无效。

Rx中的所有运算符(WhereSelect等)都会强制执行此规则,即使源不符合此规则。

答案 1 :(得分:0)

我不确定我是否正确理解了你的问题,但为什么你不能在不同的Thread上执行你所拥有的任何逻辑,或者如果它足够小就可以将它推到ThreadPool上?

以下是一个例子:

ThreadPool.QueueUserWorkItem(o=>
{
    _paidSubj.OnNext(this); // Raise PAID event 
});

我对Subject上的数据类型感到困惑,我从未见过C#中的那个类......是你创建的吗? OnNext是一个被引发的事件还是一个方法?如果OnNext是一个事件,那么您可以使用BeginInvoke异步调用它:

_paidSubj.OnNext.BeginInvoke(this, null, null);

<强>更新

如果实现这种异步行为,将会发生一件重要的事情:如果通过传递IObserver通知Order,当您尝试读取数据时,实际上可能会有一些不一致订单继续修改其Read线程中的缓冲区时,观察者(即订单缓冲区)。所以至少有两种方法可以解决这个问题:

  1. 限制对使用锁定进行修改的内存的访问。
  2. 仅通知观察者您希望其查看的相关信息:
    一个。将信息作为值传递(不作为参考) 湾通过创建传输信息的不可变结构。
  3. P.S。 你从哪里得到SubjectSubject应该是OrderObserver吗?