2011-08-27 71 views
6

我是Rx的新手。我可以看到使用熱觀測量的一些實實在在的好處,但是我最近問的差異是一個寒冷的觀察到的,等效枚舉之間是什麼(請參見下面的代碼片段)的問題...RX中可觀察到的冷態和正常的區別

var resRx = Observable.Range(1, 10); 
    var resOb = Enumerable.Range(1, 10); 

誰能解釋很簡單,兩者之間的區別是什麼,以及從冷觀察者和可枚舉者中獲得的好處。

回答

15

這兩者之間有幾個區別。

誰控制了「枚舉」

隨着觀察到的(熱或冷),它是可觀察的,確定什麼的線程返回的值時,和。另一方面,enumerable在請求它時獲取每個值,並在請求枚舉的線程上處理。

代碼流

處理可枚舉在一個典型的做法對於每個循環(或偶爾獲得枚舉和使用而循環)。在繼續之前,您的代碼通常會處理所有值。觀察對象需要回調。阻止你的代碼的進一步執行(比如說不要退出控制檯應用程序)需要額外的代碼。有些觀察對象的阻塞操作符,如First,但它們是例外情況,而不是正常使用的規則。

以這個簡單的示例程序爲例。使用枚舉值,在繼續下一部分之前,所有的值都被寫入。但是,可觀察值的值不能保證永遠不會被寫入。在程序終止之前寫入多少值幾乎是一個競爭條件。

static void Main(string[] args) 
{ 
    var xs = Enumerable.Range(1, 10); 
    foreach (var x in xs) 
    { 
     Console.WriteLine(x); 
    } 
    //at this point, all values have been written 

    var ys = Observable.Range(1, 10); 
    ys.Subscribe(y => Console.WriteLine(y)); 
    //at this point, no values have been written (in general) 

    //either add a Console.ReadKey or some sort of wait handle that 
    //is set in the OnCompleted of the observer to get values 
} 

異步進程

就像你必須編寫額外的代碼來阻止和等待觀察的,編寫使用異步進程一個IEnumerable需要一些額外的工作。這就是兩者之間真正的區別。

例如,在我目前正在處理的應用程序中,我需要搜索可能連接到串行端口的設備。 IObservable非常適合這種情況,因爲它允許我進行回調,並在每次找到設備時通知應用程序,而無需阻止以及何時完成操作。這個可觀察的資格被視爲可觀察,因爲它不會推出數據,除非有訂戶,並且每個訂閱都會獲得所有結果。 (與典型的冷觀察不同,我在訂閱之前開始工作,但沒有數據丟失,因爲它被緩衝到重播主題中。)但是,由於異步將其轉換爲Enumerable並不合理性質。

+0

感謝Gideon ...偉大的洞察力。 –

6

幾乎所有你習慣了的「Enumerables」都是「冷」Enumerables?爲什麼?因爲如果您要兩次對Enumerable.Range進行ForEach,就會得到兩倍的數字。

如果Enumerable.Range是一個Hot Enumerable,它只會給你一個列表,而第二個ForEach只會是空的。

對於Rx,Cold Observable意味着每次調用Subscribe(相當於Rx中的ForEach)時,都會收到一個新的東西列表。像FromEvent這樣的熱點觀察者不會在每次訂閱時給你一個新的事件流,它只是另一個連接到同一事件流的連接。

雖然Rx的優勢是什麼?能夠將該範圍轉換爲異步請求:

IObservable<Image> fetchImageByIndex(int imageIndexOnSite); 

Observable.Range(0, 10) 
    .SelectMany(x => fetchImageByIndex(x)) 
    .Subscribe(image => saveImageToDisk(image)); 
相關問題