可观察的集合OnNext没有触发

时间:2016-02-06 01:22:43

标签: system.reactive

我有这个非常简单的可观察集合,并且OnNext没有触发。

List<int> intList = new List<int>(){1,2,3};
IObservable<int> observableList = intList.ToObservable();

IDisposable subscription = observableList.Subscribe(
    x =>  Console.WriteLine("Received {0} from source.", x),        
    ex => Console.WriteLine( "OnError: " + ex.Message ),        
    ( ) => Console.WriteLine( "OnCompleted" )        
    ); 
intList.Add(4);

我得到的输出如下。

从来源收到1。

从消息来源收到2。

从消息来源收到3。

OnCompleted

我期待&#34;从源头收到4。&#34;在我将4添加到列表后。

有人可以说明我做错的地方。我是新的Rx

2 个答案:

答案 0 :(得分:2)

这一切都取决于您的操作顺序。

如果您构建代码如下:

List<int> intList = new List<int>() { 1, 2, 3 };

IObservable<int> observableList = intList.ToObservable();

intList.Add(4);

IDisposable subscription =
    observableList
        .Subscribe(
            x => Console.WriteLine("Received {0} from source.", x),
            ex => Console.WriteLine("OnError: " + ex.Message),
            () => Console.WriteLine("OnCompleted"));

...然后它按预期工作。

问题是.Subscribe.ToObservable()的当前主题上运行。实际的代码运行是return (IObservable<TSource>) new ToObservable<TSource>(source, SchedulerDefaults.Iteration);SchedulerDefaults.Iteration是当前主题。

您可以使用以下代码查看:

List<int> intList = new List<int>() { 1, 2, 3 };

IObservable<int> observableList = intList.ToObservable();

Console.WriteLine("Before Subscription");

IDisposable subscription =
    observableList
        .Subscribe(
            x => Console.WriteLine("Received {0} from source.", x),
            ex => Console.WriteLine("OnError: " + ex.Message),
            () => Console.WriteLine("OnCompleted"));

Console.WriteLine("After Subscription, Before Add");

intList.Add(4);

Console.WriteLine("After Add");

当我跑步时,我得到:

Before Subscription
Received 1 from source.
Received 2 from source.
Received 3 from source.
OnCompleted
After Subscription, Before Add
After Add

所以.Add甚至没有发生,直到订阅完成为止。

现在,如果我尝试通过将代码更改为intList.ToObservable(Scheduler.Default)来解决这个问题,那么我会遇到一个新问题。运行上面的代码我得到了这个:

Before Subscription
After Subscription, Before Add
After Add
Received 1 from source.
OnError: Collection was modified; enumeration operation may not execute.

现在显然,我们遇到了并发问题。你不应该试图操纵集合并同时迭代它们。

答案 1 :(得分:1)

这只是因为List上的.ToObservable()只会在每次订阅时向您提供列表中的当前项目,而不会持续通知添加的项目。对于实现IEnumerable的只读集合也是如此。

您可以使用其他集合,它们将按预期工作。 例如的ObservableCollection

或者,您可以找到任何提供更改通知的集合类型(collection.Added + = etc ...),并使用Observable.FromEvent来挂接后续通知。

同样值得理解的是IEnumerable.ToObservable是一个冷可观察因素,因此,为什么订阅顺序也很重要(按照第一个答案)。