6

I am trying to use reactive extensions (Rx) to create a hot observable that can be subscribed by multiple users that all get the values that are pushed to them. I can do this using subjects as below:

var subj = new Subject<int>();
var observable = subj.AsObservable();
observable.Subscribe(x => Console.WriteLine("1 Number: {0}", x));
observable.Subscribe(x => Console.WriteLine("2 Number: {0}", x));

subj.OnNext(1);
subj.OnNext(2);
subj.OnNext(3);
  //and so on

but I have read that subjects are for "experimental" use and I would like to do the same thing using Observable.Create factory method. I have looked around and there are plenty of examples of creating cold observables using the Create method but I would like to have the same behavior as the code above produces.

Thanks for any help.

Nick

Nick Tucker
  • 323
  • 7
  • 14

1 Answers1

3

Your question can be split into two separate ones.

1. How to create Observable without a subject?

There are a number of methods, listed in this perfect book. Observable.Create is just one of them, but in order to get a sequence of values like in your example (1, 2, 3) I would simply use

var source = Observable.Range(1, 3);

But, as you probably noticed, streams created this way will be cold observables. This leads to second question:

2. How to turn cold observable into hot and share results between subscribers?

In order to do that, you need a Publish function. It allows for sharing Rx stream between subscribers. Try this out:

var sourceHot = Observable.Range(1, 3).Publish();
sourceHot.Subscribe(x => Console.WriteLine("1 Number: {0}", x));
sourceHot.Subscribe(x => Console.WriteLine("2 Number: {0}", x));
var disp = sourceHot.Connect();

Note that if you don't want to manually call Connect/Disconnect, you can use a RefCount function. Also note that stream.Publish() is exactly the same as calling stream.Multicast(new Subject<T>()).

I highly recommend reading Sharing in RX: Publish, Replay, and Multicast article, which explains this topic in depth.

pmbanka
  • 1,902
  • 17
  • 24
  • Thanks for your reply. I had read the article you mentioned and it describes exactly what I want to do but I it says that RefCount scarifies some safety and something that I had not mentioned in my original question is that I would have subscribers connecting and disconnecting periodically which, if I have read it correctly, could be the cause of issues? – Nick Tucker Dec 16 '15 at 14:02
  • 1
    The only "danger" of using `RefCount` is the fact that when last subscriber unsubscribes, the connection to underlying stream is closed. If you want to keep your underlying stream "alive" all the time (regardless of subscribers work), maintain your `ConnectableObservable` by hand, calling `Connect` and `Disconnect` like in code snippet in my answer. Hope this helps :) (also, don't worry if something is still unclear for you - I had to read tis article a few times before I really felt I understand it). – pmbanka Dec 16 '15 at 14:09
  • 1
    `Observable.Range` works for this contrived example, but what if the values posted to the sequence are more arbitrary? And the elapsed time/work between generating their values is also arbitrary? The OP suggested that Subjects are "experimental", but would you agree that in some cases, such as publishing of business-y events, or status changes of work items flowing through a batch processing system, it's your only alternative and totally appropriate in a production system? (I'm relatively new to Rx, so that's not rhetorical.) – Todd Menier Aug 09 '18 at 00:30
  • 2
    @ToddMenier I would not agree with naming Subjects "experimental". There is nothing wrong or not-production-worthy about them. I believe that a rule of thumb would be to try to avoid them (e.g. use `Observable.Create` if possible), but if you can't see any better solution, go for them. See also https://stackoverflow.com/a/21824601/1108916 – pmbanka Aug 09 '18 at 13:19
  • 2
    @pmbanka Thanks for confirming. I found this extremely helpful too: http://davesexton.com/blog/post/To-Use-Subject-Or-Not-To-Use-Subject.aspx – Todd Menier Aug 09 '18 at 14:22
  • 2
    Above link is indeed useful. However you need to use https nowadays or it 404s. https://www.davesexton.com/blog/post/To-Use-Subject-Or-Not-To-Use-Subject.aspx – 3dGrabber Nov 16 '21 at 17:01