2013-03-23 83 views
1

閱讀IntroToRx網站,它鼓勵採用有利於Observable.Create helper方法的學科。推新價值

正如我所看到的,OnNext方法只能調用到訂閱方法,因爲它是我有機會觀察對象的唯一部分。

如果我想推新值是創建後? 我是否「被迫」使用主題?

+0

解釋更多關於你想要實現的內容 – Phil 2013-03-23 15:53:15

+0

取決於你在「推」什麼 - 有點簡化 - 如果你只是處理其他源的事件,數據(重新處理它們並向前傳遞) ,那麼主題可以避免(並且該線有點「瘦」,你可能不會想,但通常有一些外部來源)。如果您實際上正在製作自己的「Feed」消息,而不是明顯的外部來源 - 那麼主體遲早會作爲解決方案出現。有關詳細信息,最好查看實際的Rx源代碼,以查看「原創者」是如何解決某些問題的。 – NSGaga 2013-03-23 16:30:14

回答

4

如果你只是探索的Rx,去了 - 使用主題,想怎麼樣,看看他們是如何工作的,發現他們的優點和缺點自己,然後再回來這裏閱讀討論爲什麼主題是不可取的問題。

主題提供更容易「快速引導」想法和複雜的Rx方案,而無需複製實際的源條件。

也就是說,他們注入狀態到什麼是一種無國界的操作鏈,所以要小心不要依賴它們。

所以,總結一下:如果你想生成序列測試/學習如何RX工作或你怎麼可能讓查詢X,使用這些科目。如果你發現自己在查詢中使用它們,那麼有一個更好的方法。

編輯:意識到我錯過了一些東西:

此外,您還詢問是否有提高流事件創作的帖子...答案是肯定的另一種方式;您可以通過Create或Return或Generate聲明一個流,它返回您定義的任何舊的基於IObservable的對象,這些對象還可以公開方法來注入事件......或者說,有一個lambda可以讓一個線程檢查一個共享列表被路由到返回流....我想我說的是,可能性是無止境的。在Observable上聲明瞭一些類似於「創建一系列事件」的方法 - 全部嘗試!編輯2:

舉例說明?當然,讓我們一起扔使用Observable.Create的東西,模仿真正的低效Subject

var running = true; 
var values = new ConcurrentQueue<int>(); 
var query = Observable.Create<int>(obs => 
{ 
    var body = Task.Factory.StartNew(()=> 
    { 
     while(running) 
     { 
      int nextValue; 
      if(values.TryDequeue(out nextValue)) 
      { 
       obs.OnNext(nextValue); 
      } 
      Thread.Yield(); 
     } 
    }); 
    return Disposable.Create(() => 
    { 
     try 
     { 
      running = false; 
      body.Wait(); 
      obs.OnCompleted();    
     } 
     catch(Exception ex) 
     { 
      obs.OnError(ex); 
     } 
    }); 
}); 
using(query.Subscribe(Console.WriteLine)) 
{ 
    values.Enqueue(1); 
    values.Enqueue(2); 
    values.Enqueue(3); 
    values.Enqueue(4); 
    Console.ReadLine(); 
} 

請注意,這只是快速和極其骯髒的示例代碼。 :)

+0

是的,這就是他正在談論的我認爲 - 跌倒到另一個IObservable是一種雞和雞蛋:) - 並涉及共享列表添加狀態 - 我試圖說如果你有什麼需要'發佈'或你需要一個狀態(作爲你所做的事情的本質),你可以歸結爲類似的解決方案。 Observable.Create(我完全同意)迫使你首先探索其他事物 - 但在開始時很難得到正確的結果。 – NSGaga 2013-03-23 18:13:28

+0

可以在創建後發佈有關推送新數據的簡單示例嗎? – Vincenzo 2013-03-24 10:23:53

+0

@Vincenzo當然,只是增加了一個簡單的例子 – JerKimball 2013-03-24 18:27:30

0

這取決於你正在嘗試做什麼。對於主題,有一些情況,但是當他們第一次開始使用Rx時,並沒有那麼多。

如何將新的數據輸入您的序列?它會來自另一個事件嗎?也許來自通信框架的消息?也許輪詢一個文件?

根據這些問題的答案,你通常會發現,你已經有某種事件源,而你只是從其他模式轉換到的Rx(事件,輪詢,回調等...)

你也別不必使用Observable.Create。您可以使用Observable.Timer/Interval來設置輪詢順序,Observable.FromEventPattern利用現有的事件,Observable.Start進行一次性異步任務樣式計算等...

由於Rx(甚至Linq)可以是相當抽象的,要求抽象的問題通常會導致非常廣泛的答案。如果您指出您正在嘗試解決的問題,那可能會爲您提供更好的答案。

+1

來源很簡單:我有幾個設備連接(網絡或串行通信),每隔X分鐘我得到他們的狀態和關聯的數據,然後推(如果不等於前一個) 。 – Vincenzo 2013-03-26 06:35:53

+0

那麼你在輪詢設備?如果是這樣,那麼我會利用調度程序或Observable.Timer。這會否定對主題的需要。 – 2013-03-26 09:25:28

+0

我想我有足夠的信息來編寫一些代碼並開始測試。非常感謝你的幫助, – Vincenzo 2013-03-26 13:06:22

0

如果您正在從外部設備接收數據,您無意通過IObserver.OnError發送信號錯誤(假設您的數據流是無窮無盡的和/或任何與通信有關的問題都在消息本身內),您只能以某種速度進行輪詢Subject的問題在於,即使在任何人訂閱之前,您可能會開始輪詢此設備(但是額外的好處是,處理您的狀態非常明顯,您創建了一個對象,它打開了COM端口,它通信併發布了值)

使用Observable.CreateObservable.Timer/Interval可能會更好 - 但懶惰是主要原因,無論如何你會管理狀態。你可能需要使用Publish()。RefCount()來防止第二次訂閱打開端口。