How to enable polling system in Rx.Net IObservable?

I have a game (based on MonoGame / XNA) with this update method:

public void Update(GameTime gameTime) { component.Update(gameTime); } 

I would like to convert this to a Reactive pattern. My current solution:

 public void Initialize() { updateSubject = new Subject<GameTime>(); component = new Component(); updateSubject.Subscribe((gameTime) => component.Update(gameTime)); } public void Update(GameTime gameTime) { updateSubject.OnNext(gameTime); } 

I'm new to Rx, so I'm still learning the best way to do something. I read that Subject should be avoided, and Observable.Create should be used instead.

Is Subject suitable here?

How could I use Observable.Create in this case?

+5
source share
2 answers

The key problem that you are facing is that you need a source for observation. In general, you can create observables from various sources from events, delegates, tasks, many observable extensions (for example, .Interval or .Generate ) and objects.

In your case, you should have a source that may have code external to your observed push values. In this case, the subject is great, but you can also use a delegate.

If you use a theme, then your code is fine. The only drawback is that you could call updateSubject.OnCompleted and end the observable.

If you want to use a delegate, your code might look like this:

 private Action<GameTime> updateGameTime = null; public void Initialize() { component = new Component(); Observable .FromEvent<GameTime>(a => updateGameTime += a, a => updateGameTime -= a) .Subscribe((gameTime) => component.Update(gameTime)); } public void Update(GameTime gameTime) { updateGameTime(gameTime); } 

Thus, the only thing you can do with updateGameTime is to pass in a new GameTime - you cannot "accidentally" end the sequence.

Now the whole problem with using objects in comparison with Observable.Create is one of the states. In your code you need to indicate the state, so the topic is in order. In general, although it’s possible it is advisable to encapsulate the state - and what Observable.Create does for you.

Take this example:

 var i = -1; var query = Observable .Range(0, 10).Select(x => { i = -i * 2; return x * i; }); 

If I subscribe to this observable twice, I get these two sequences:

(1)

  0 
 -4 
 16 
 -48 
 128 
 -320 
 768 
 -1792 
 4096 
 -9216 

(2)

  0 
 -4096 
 16384 
 -49152 
 131072 
 -327680 
 786432 
 -1835008 
 4,194,304 
 -9437184 

The sequence changes because I used the state (i.e. var i = -1; ).

If I wrote code using Observable.Create , I could avoid this state:

 var query = Observable .Create<int>(o => { var i = -1; return Observable .Range(0, 10).Select(x => { i = -i * 2; return x * i; }) .Subscribe(o); }); 

This is still the same request, but the state is encapsulated, so if I sign up twice, I get:

(1)

  0 
 -4 
 16 
 -48 
 128 
 -320 
 768 
 -1792 
 4096 
 -9216 

(2)

  0 
 -4 
 16 
 -48 
 128 
 -320 
 768 
 -1792 
 4096 
 -9216 

There are times when you write complex queries that might seem that using the object would make it much easier, and in general, where errors occur. You should always try to find an approach to a clean operator before using objects in this case. If you cannot then encapsulate the use of the object in Observable.Create .

It seems like using the object is fine, because you need this external state.

+6
source

Just indicating that you are coding unessecarily, Rx is used.

 public void Initialize() { //updateSubject = new Subject<GameTime>(); component = new Component(); //updateSubject.Subscribe((gameTime) => component.Update(gameTime)); } public void Update(GameTime gameTime) { //updateSubject.OnNext(gameTime); component.Update(gameTime) } 

Here I deleted Subject and simply moved on to the component Update method to illustrate this point.

Are you looking for a private survey method? In this case, Observable.Interval might be a good place to start.

0
source

All Articles