C# 一个观测者能用Rx安全地监听多个观测者吗?

C# 一个观测者能用Rx安全地监听多个观测者吗?,c#,system.reactive,observer-pattern,observable,C#,System.reactive,Observer Pattern,Observable,我试图了解多个可观测事件如何通过Rx流化为一组事件。但是当我运行下面的代码时,我得到了一个异常。那么这是否意味着多个观察者总是因为违反Rx语法而容易发生异常呢?我的意思是,如果多个观察者中的两个偶然在同一时间产生一个事件(任何两个观察者都有可能在同一时间产生),它应该给出一个例外 DateTimeOffset start; object sync = new object(); var subject = new Subject<long>();

我试图了解多个可观测事件如何通过Rx流化为一组事件。但是当我运行下面的代码时,我得到了一个异常。那么这是否意味着多个观察者总是因为违反Rx语法而容易发生异常呢?我的意思是,如果多个观察者中的两个偶然在同一时间产生一个事件(任何两个观察者都有可能在同一时间产生),它应该给出一个例外

DateTimeOffset start;
        object sync = new object();
        var subject = new Subject<long>();
        var observer = Observer.Create<long>(c =>
        {
            lock (sync)
            {
                Console.WriteLine(c);
            }
        })
            ;

        var observable1 = Observable.Interval(TimeSpan.FromSeconds(2));
        var observable2 = Observable.Interval(TimeSpan.FromSeconds(5));
        var observable3 = Observable.Never<long>().Timeout
            (start = DateTimeOffset.Now.AddSeconds(15),
             (new long[] { 1 }).ToObservable());
        var observable4 = Observable.Never<long>().Timeout(start);
        observable1.Subscribe(observer);
        observable2.Subscribe(observer);
        observable3.Subscribe(observer);
        observable4.Subscribe(observer);
        Thread.Sleep(20000);
DateTimeOffset开始;
对象同步=新对象();
var subject=新的subject();
var observer=observer.Create(c=>
{
锁定(同步)
{
控制台写入线(c);
}
})
;
var Observable 1=可观测的时间间隔(从秒(2)开始的时间跨度);
var Observable 2=可观测的时间间隔(从秒(5)开始的时间跨度);
var observed3=可观测的。从不()超时
(开始=DateTimeOffset.Now.AddSeconds(15),
(新的long[]{1}).ToObservable());
var observe4=observeble.Never().超时(开始);
可观察1.订阅(观察员);
2.订阅(观察员);
可观察的3.订阅(观察者);
可观察的4.认购(观察员);
睡眠(20000);
谢谢吉迪恩的解释。这是我得到的一个例外。你是对的,这是一个timeoutexception。这是一个编码错误。谢谢

System.TimeoutException: The operation has timed out.
   at System.Reactive.Observer.<Create>b__8[T](Exception e)
   at System.Reactive.AnonymousObserver`1.Error(Exception exception)
   at System.Reactive.AbstractObserver`1.OnError(Exception error)
   at System.Reactive.Subjects.Subject`1.OnError(Exception error)
   at System.Reactive.AnonymousObservable`1.AutoDetachObserver.Error(Exception e
xception)
   at System.Reactive.AbstractObserver`1.OnError(Exception error)
   at System.Reactive.AnonymousObservable`1.AutoDetachObserver.Error(Exception e
xception)
   at System.Reactive.AbstractObserver`1.OnError(Exception error)
   at System.Reactive.Linq.Observable.<>c__DisplayClass28c`1.<>c__DisplayClass28
e.<Throw>b__28b()
   at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action
action)
   at System.Reactive.Concurrency.ImmediateScheduler.Schedule[TState](TState sta
te, Func`3 action)
   at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Actio
n action)
   at System.Reactive.Linq.Observable.<>c__DisplayClass28c`1.<Throw>b__28a(IObse
rver`1 observer)
   at System.Reactive.AnonymousObservable`1.<>c__DisplayClass1.<Subscribe>b__0()

   at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action
action)
   at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
   at System.Reactive.Concurrency.ScheduledItem`1.Invoke()
   at System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run()
   at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState
 state, TimeSpan dueTime, Func`3 action)
   at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState
 state, Func`3 action)
   at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Actio
n action)
   at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
   at System.Reactive.Linq.Observable.<>c__DisplayClass543`1.<>c__DisplayClass54
5.<Timeout>b__53f()
   at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action
action)
   at System.Reactive.Concurrency.ThreadPoolScheduler.<>c__DisplayClass8`1.<Sche
dule>b__6(Object _)
   at System.Threading._TimerCallback.TimerCallback_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
ontextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading._TimerCallback.PerformTimerCallback(Object state)
System.TimeoutException:操作已超时。
在System.Reactive.Observator.b__8[T](异常e)
at System.Reactive.AnonymousObserver`1.错误(异常)
at System.Reactive.AbstractObserver`1.OnError(异常错误)
at System.Reactive.Subject.Subject`1.OnError(异常错误)
在System.Reactive.AnonymousObservable`1.AutoDetachObserver.Error(异常e
例外情况)
at System.Reactive.AbstractObserver`1.OnError(异常错误)
在System.Reactive.AnonymousObservable`1.AutoDetachObserver.Error(异常e
例外情况)
at System.Reactive.AbstractObserver`1.OnError(异常错误)
在System.Reactive.Linq.Observable.c__DisplayClass28c`1.c__DisplayClass28
e、 b__28b()
在System.Reactive.Concurrency.Scheduler.Invoke(isScheduler调度器,操作
(行动)
at System.Responsive.Concurrency.ImmediateScheduler.Schedule[TState](TState sta
te,Func`3行动)
在System.Reactive.Concurrency.Scheduler.Schedule(ISScheduler Scheduler,Actio
n行动)
在System.Reactive.Linq.Observable.c__DisplayClass28c`1.b__28a(IObse
(1名观察员)
在System.Reactive.AnonymousObservable`1.c_uuuDisplayClass1.b_uu0()
在System.Reactive.Concurrency.Scheduler.Invoke(isScheduler调度器,操作
(行动)
在System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()中
在System.Reactive.Concurrency.ScheduledItem`1.Invoke()处
在System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run()中
在System.Responsive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState)中
状态,时间跨度,时间跨度,函数'3操作)
在System.Responsive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState)中
国家,职能(3行动)
在System.Reactive.Concurrency.Scheduler.Schedule(ISScheduler Scheduler,Actio
n行动)
at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
在System.Reactive.Linq.Observable.c__显示类别543`1.c__显示类别54
5.b__53f()
在System.Reactive.Concurrency.Scheduler.Invoke(isScheduler调度器,操作
(行动)
在System.Responsive.Concurrency.ThreadPoolScheduler.c__DisplayClass8`1.b__6(对象)
在System.Threading.\u TimerCallback.TimerCallback\u上下文(对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,C
ontextCallback回调,对象状态,布尔值ignoreSyncCtx)
在System.Threading.\u TimerCallback.PerformTimerCallback(对象状态)

是的,一个观察者可以监听多个观察者。最好的例子是
Merge
操作符。内置操作符都将遵循RX语法,并且通常会在不遵循RX语法的源上强制执行RX语法

Observer.Create
获得的
IObserver
就是这样一种情况。一旦调用OnError或OnCompleted,它将忽略将来对OnNext的任何调用。这意味着使用同一个观察者订阅一个观察者,然后订阅第一个观察者之后的另一个观察者将不起作用,因为来自第一个观察者的终止消息将导致观察者忽略来自第二个观察者的消息。为了解决这一问题,诸如
Merge
Concat
、和
OnErrorResumeNext
(以及其他)之类的操作符在内部使用多个观察者,并且不将完成消息(OnError和/或OnCompleted,取决于操作符的语义)从最后一个观察者以外的任何观察者传递给外部观察者

您没有提到您将遇到什么异常,但我想是您从
observable4
获得的超时导致的错误。如果您没有提供另一个用于超时的可观察对象,将调用观察者的
OnError
,而
Subscribe
观察者的默认
OnError
。创建不接受错误处理程序的
重载只需抛出异常即可


虽然这显然是示例/测试代码,但我想指出的是,即使您不再将消息传递给您的
OnNext
,所有其他可观察对象都会在该异常之后继续运行。使用
Merge
为您跟踪此信息,或者跟踪描述中的所有一次性物品,并在收到完成消息时自行处理<代码>CompositeDisposable(在
System.Reactive.Disposables
)中)有助于实现这一点。

您确实不应该在此处使用锁,但如果您确实想让它工作,您可以执行以下操作:

var x = Observable.Create<T>(subj => { /* Fill it in*/ })
    .Multicast(new Subject<T>());

// Set up your subscriptions Here!

// When you call the Connect, whatever is in the Observable.Create will be called
x.Connect();
var x=Obs