2016-02-06 188 views
1

我有這個非常簡單的可觀察集合,並且OnNext沒有射擊。可觀察集合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

我期待「從源頭收到4」。添加4後列出。

有人可以拋出一些光在我做錯了。我是新Rx

+1

你應該看看[dynamic-data](http://dynamic-data.org/)。 – Dorus

回答

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. 

現在很明顯,我們有一個併發問題。您不應該嘗試操作集合並同時迭代它們。

+0

謝謝。意味着我需要更多地瞭解。 – VivekDev

+0

@VivekDev - 你覺得你有什麼困難是什麼? – Enigmativity

+1

@VivekDev - 只是一件事。我已經看到人們認爲列表中的'.ToObservable()'然後會使觀察者在訂閱之後響應添加到列表**中的新項目。你認爲是這樣嗎? – Enigmativity

1

這很簡單,因爲列表中的.ToObservable()只會在您每次訂閱它時纔會向列表中的當前項目提供您,而沒有正在進行的添加項目通知。對於實現IEnumerable的只讀集合也是如此。

您還可以使用其他集合,而不是按預期方式工作。 例如ObservableCollection

另外,你可以找到任何集合類型,它給出變化通知(collection.Added + =等等...),並使用Observable.FromEvent掛接後續通知。

還值得了解IEnumerable.ToObservable是一個冷觀察,因此,爲什麼訂閱的順序也很重要(根據第一個答案)。