How do you fan out observables with reactive extensions - c#

I have a service that I would like to turn into a rx observable
The service has an interface of
IEnumerable<Price> FetchUpdatedPrices()
{
//do work to return changed data since last update
}
My idea was to use rx to allow a consumer to subscribe to updates. The implementation would poll the service every x seconds and call the observer.
I came up with the following
public IDisposable Subscribe(IObserver<IEnumerable<Price>> observer)
{
IObservable<IEnumerable<Price>> updatedPrices = Observable.Interval(new TimeSpan(0, 0, 1))
.Select(r => FetchUpdatedPrices());
return updatedPrices.Subscribe(observer);
}
The problem is I would like the observer to see an IObservable<Price> rather than an IObservable<IEnumerable<Price>>
Could anyone give this Rx noob any pointers on how to do this?

How about SelectMany?
IObservable<IEnumerable<Price>> updatedPrices = Observable.Interval(new TimeSpan(0, 0, 1))
.SelectMany(r => FetchUpdatedPrices());

Related

Notifying asynchronous subject from another observable using Rx .NET

I'm trying to notify listeners who subscribed to Subject _sub from another observable and after that log some message in Do handler. I'm calling OnNext and everything would work fine if _sub wasn't asynchronous. The problem here is that there is no OnNextAsync function which I would await in the first observable. What is the best way to do this?
class Program
{
private static Subject<int> _sub = new Subject<int>();
static void Main(string[] args)
{
_sub.SelectMany(async _ =>
{
Console.WriteLine("SUB START: " + _);
await Task.Delay(3000);
Console.WriteLine("SUB END: " + _);
return 1;
}).Subscribe();
Start();
}
public static void Start()
{
int count = 0;
Observable.Interval(TimeSpan.FromSeconds(5)).Select(x =>
{
Console.WriteLine("START INTERVAL");
_sub.OnNext(count++); //onNext is not awaitable
Console.WriteLine("END INTERVAL");
return 1;
})
.Do(_ => Console.WriteLine("ALL FINISHED"))
.Subscribe();
Console.WriteLine("READLINE");
Console.ReadLine();
}
}
Result:
READLINE
START INTERVAL
SUB START: 0
END INTERVAL
ALL FINISHED
SUB END: 0
Expected result:
READLINE
START INTERVAL
SUB START: 0
SUB END: 0
END INTERVAL
ALL FINISHED
An observable should not rely on the behavior of its observers.
I suggest you rethink the whole thing. What you're doing looks more interactive than reactive.
I'm going to echo Paulo for clarity:
Observables shouldn't care about Observers. While an Observable will wait on its synchronous Observers, it's best to think of this as an accident of implementation. An observable doesn't wait at all on an asynchronous Observer. Either way, the waiting shouldn't be relied upon.
You should really re-think how you're doing this. You're using a reactive library to write interactive code. Probably either the wrong choice of tool or a misuse of the tool.
Your code is littered with Rx code-smells. Think of reactive code as a flowchart. A flowchart of your code would look like spaghetti. It should look more like a binary tree.
This sounds like an XY problem: I would suggest re-phrasing your question with what you're trying to accomplish.

What are the functional benefits of recursive scheduling in System.Reactive?

I'm current reading http://www.introtorx.com/ and I'm getting really interested in stripping Subject<T> out of my reactive code. I'm starting to understand how to encapsulate sequence generation so that I can reason better about a given sequence. I read a few SO questions and ended up reading about scheduling. Of particular interest is recursive scheduling, using the Schedule(this IScheduler scheduler, Action<TState,Action<TState>>)overloads - like this one.
The book is starting to show its age in a few areas, and the biggest i see is that it never compares its techniques to alternatives that may be achieved using the Task and async/await language features. I always end up feeling like I could write less code by ignoring the book advice and using the asynchronous toys, but the back of my mind nags me about being lazy and not learning the pattern properly.
With that, here is my question. If I wanted to schedule a sequence at an interval, support cancellation and perform work on a background thread, I might do this:
static void Main(string[] args)
{
var sequence = Observable.Create<object>(o =>
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
DoWerk(o, cancellationTokenSource);
return cancellationTokenSource.Cancel;
});
sequence.Subscribe(p => Console.Write(p));
Console.ReadLine();
}
private static async void DoWerk(IObserver<object> o, CancellationTokenSource cancellationTokenSource)
{
string message = "hello world!";
for (int i = 0; i < message.Length; i++)
{
await Task.Delay(250, cancellationTokenSource.Token);
o.OnNext(message[i]);
if (cancellationTokenSource.IsCancellationRequested)
{
break;
}
}
o.OnCompleted();
}
Note the use of async void to create concurrency without explicitly borrowing a thread pool thread with Task.Run(). await Task.Delay() will, however, do just that but it will not lease the thread for long.
What are the limitations and pitfalls here? What are the reasons that you might prefer to use recursive scheduling?
I personally wouldn't use await Task.Delay(250, cancellationTokenSource.Token); as a way to slow down a loop. It's better than Thread.Sleep(250), but it's still code smell to me.
I would look at it that you should use a built-in operator in preference to a roll-your-own solution like this.
The operator you need is one of the most powerful, but often overlooked. Try Observable.Generate. He's how:
static void Main(string[] args)
{
IObservable<char> sequence = Observable.Create<char>(o =>
{
string message = "hello world!";
return
Observable
.Generate(
0,
n => n < message.Length,
n => n + 1,
n => message[n],
n => TimeSpan.FromMilliseconds(250.0))
.Subscribe(o);
});
using (sequence.Subscribe(p => Console.Write(p)))
{
Console.ReadLine();
}
}
This is self-cancelling (when you call .Dispose() on the subscription) and produces values every 250.0 milliseconds.
I've continued to use the Observable.Create operator to ensure that the message variable is encapsulated within the observable - otherwise it is possible for someone to change the value of message as the observable is working with it and thus break it.
As an alternative, that might not be as efficient with memory, but is self-encapsulating, try this:
IObservable<char> sequence =
Observable
.Generate(
"hello world!",
n => !String.IsNullOrEmpty(n),
n => n.Substring(1),
n => n[0],
n => TimeSpan.FromMilliseconds(250.0));
And, finally, there's nothing "recursive" about the scheduling in your question. What did you mean by that?
I finally figured out what you're looking at. I missed it in the question.
Here's an example using the recursive scheduling:
IObservable<char> sequence = Observable.Create<char>(o =>
{
string message = "hello world!";
return Scheduler.Default.Schedule<string>(message, TimeSpan.FromMilliseconds(250.0), (state, schedule) =>
{
if (!String.IsNullOrEmpty(state))
{
o.OnNext(state[0]);
schedule(state.Substring(1), TimeSpan.FromMilliseconds(250.0));
}
else
{
o.OnCompleted();
}
});
});

Can I check in observer if a new item arrived to the observable?

I'm accessing a memory area that belongs to a different computational process.
There are relatively infrequent changes in the area and I need to run a calculation when there are changes. I get notifications on change, but I need to wait a bit to make sure that no more changes are being made. I model it like this:
var readyToBeProcessed = changed
.Select(x => DateTime.Now)
.Throttle(TimeSpan.FromSeconds(5));
However my calculations take quite some time, and it is possible that memory changes while I'm doing them. In this case I need to mark this particular round of calculations as invalid.
But how do I know in my observer, when I finished the calculation, if another event arrived or not, while processing current event? If there are no events arrive since I started the calculation, then it's valid and I can store the result.
In practice, it's very rarely, that the event arrive in the pattern (fast enough) that allow the calculation to become invalid, still I'd like to cater for this case.
Note: I realize that I cannot guarantee to have always valid calculations. There is a small time between a change in memory is made and the time I receive the event. It is entirely possible, that the sequence is like this 1) I'm doing the calculation 2) memory changes 3) I finish the calculation and check the event, and decide the calculation is valid 4) memory change event arrives. I'm happy to live with this for now
readyToBeProcessed.Subscribe(x =>
{
Log.Info("Start work...");
// Do calculation here
...
// When finished
if (Is there a new item)
{
Log.Info("There were changes while we worked... Invalidating");
Invalidate();
}
else
{
Log.Info("Succeeded");
}
}, cancellationToken);
Is Reactive bad fit for this task?
Rx is actually a great choice here, I think, though you may need to model it a bit more explicitly.
Think of there being really five type of events: Item changes, do-Work-begins, and do-Work-ends, Invalidates, and Succeededs (I wish I could use better names, but I'm working off what you wrote).
Here's a marble diagram of how they would work:
t(sec) : 0--1--2--3--4--5--6--7--8--9--10-11-12-13-14-15-16...
item-change : *-*--**-----------------*-------------------------...
do-Work-begins: ---------------------*-----------------*----------...
do-Work-ends : -------------------------*------------------*-----...
invalidate : -------------------------*------------------------...
succeeded : --------------------------------------------*-----...
We begin work once there has been a 5 second lull in item changes. If there has been any changes during the work time, we want to invalidate upon work-completion. If not, we want to observe success.
var doWorkBegins = changed
.Select(x => DateTime.Now)
.Throttle(TimeSpan.FromSeconds(5));
var doWorkEnds = doWorkBegins
.SelectMany(x =>
{
Log.Info("Start work...");
// DoWork();
//
// should return an observable that returns a single value when complete.
// If DoWork is just a void, then can use
// return Observable.Return(Unit.Default);
});
var lists = changed
.Buffer(() => doWorkEnds)
.Publish().RefCount();
var succeeded = lists
.Where(l => l.Count == 0);
var invalidate = lists
.Where(l => l.Count > 0);
invalidate.Subscribe(x =>
{
Log.Info("There were changes while we worked... Invalidating");
Invalidate();
}, cancellationToken);
succeeded.Subscribe(x =>
{
Log.Info("Succeeded");
}, cancellationToken);
Ideally, I would recommend you use a Task for keeping track of your work, then you can use:
readyToBeProcessed
.Select(evt => Observable.StartAsync<Unit>(async (cancellationToken) =>
{
//pass cancellationToken to work
var result = await DoWork(cancellationToken);
//test token if needed
return result;
}))
.Switch()
.Subscribe();
When the next item arrives, the current token will be canceled.

Track the (number of) observers in an Observable?

I have an observable which represents a stream of stock prices. If there are no observers on my observable sequence I'd like to be able to disconnect from the remote server that is supplying the stream of prices, but I don't want to do that until every observer has called Dispose(). Then in a similar fashion, when the first person calls Subscribe I'd like to reconnect to the remote server.
Is there a way to figure out how many observers have called subscribe on an observable? Or perhaps a way to know when observers are calling Subscribe or Dispose?
I would simply use RefCount / Publish. I always feel like if I'm implementing IObservable I'm working way too hard.
myColdObservable.Publish().RefCount();
This will make your observable stop pulsing after everyone has disconnected. Here's a sample:
var coldObservable = Observable
.Interval(TimeSpan.FromSeconds(1))
.ObserveOn(Scheduler.TaskPool)
.Select(_ => DoSomething());
var refCountObs = coldObservable.Publish().RefCount();
CompositeDisposable d = new CompositeDisposable();
d.Add(refCountObs.Subscribe(n => Console.WriteLine("First got: " + n)));
d.Add(refCountObs.Subscribe(n => Console.WriteLine("Second got: " + n)));
d.Add(refCountObs.Subscribe(n => Console.WriteLine("Third got: " + n)));
//Wait a bit for work to happen
System.Threading.Thread.Sleep(10000);
//Everyone unsubscribes
d.Dispose();
//Observe that DoSomething is not called.
System.Threading.Thread.Sleep(3000);
This does not cover the case where you actually want to know the number of subscribers, but I think this fits with your requirements of stopping work if there are no subscribers.
Bit of an old one but I came across this post as I had a problem where I needed to know the number of subscribers. Using Bart's suggestion I came up with this extension.
public static IObservable<T> CountSubscribers<T>(this IObservable<T> source, Action<int> countChanged)
{
int count = 0;
return Observable.Defer(() =>
{
count = Interlocked.Increment(ref count);
countChanged(count);
return source.Finally(() =>
{
count = Interlocked.Decrement(ref count);
countChanged(count);
});
});
}
In general, don't implement IObservable; typically there's already soemthing in Rx that can help you out, either directly or through composition. If you ever have to implement IObservable, use Observable.Create to do so, in order to get all the guaranteed required for the observer contract etc.
As for your problem - the suggestion of using Publish and RefCount is exactly the composition you're looking for. If you want to count yourself for some reason, use Observable.Defer to intercept subscriptions, possibly with Observable.Finally to intercept sequence terminations. Or, wrap the source with an Observable.Create, forward the observer to the wrapped sequence, and wrap the returned IDisposable with counting logic (using Disposable.Create).
Cheers,
-Bart (Rx team)
IObservable<T> is an interface that you can implement. In the Subscribe method of the interface you can keep track of observers by maintaining a list internally.
Following code snippet is from MSDN.
private List<IObserver<Location>> observers;
public IDisposable Subscribe(IObserver<Location> observer)
{
if (! observers.Contains(observer))
observers.Add(observer);
// ------- If observers.Count == 1 create connection. -------
return new Unsubscriber(observers, observer);
}
private class Unsubscriber : IDisposable
{
private List<IObserver<Location>>_observers;
private IObserver<Location> _observer;
public Unsubscriber(List<IObserver<Location>> observers, IObserver<Location> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
// ----------- if observers.Count == 0 close connection -----------
}
}

Using Rx to synchronize asynchronous events

I want to put Reactive Extensions for .NET (Rx) to good use and would like to get some input on doing some basic tasks. To illustrate what I'm trying to do I have a contrived example where I have an external component with asyncronous events:
class Component {
public void BeginStart() { ... }
public event EventHandler Started;
}
The component is started by calling BeginStart(). This method returns immediately, and later, when the component has completed startup, the Started event fires.
I want to create a synchronous start method by wrapping the component and wait until the Started event is fired. This is what I've come up with so far:
class ComponentWrapper {
readonly Component component = new Component();
void StartComponent() {
var componentStarted =
Observable.FromEvent<EventArgs>(this.component, "Started");
using (var startedEvent = new ManualResetEvent(false))
using (componentStarted.Take(1).Subscribe(e => { startedEvent.Set(); })) {
this.componenet.BeginStart();
startedEvent.WaitOne();
}
}
}
I would like to get rid of the ManualResetEvent, and I expect that Rx has a solution. But how?
PL's answer if perfectly good for your spec, but I thought you might get better results by not fighting RX with .First() but embracing it with creating an observable to your component:
public static IObservable<Unit> AsObservable(this Component component)
{
return Observable.Defer(() =>
{
component.BeginStart();
return Observable
.FromEvent<EventArgs>(component, "Started")
.Select(_ => new Unit());
});
}
Then you could use it as blocking:
new Component().AsObservable().First();
Non - blocking:
new Component().AsObservable().Subscribe(_ => Console.WriteLine("Done"));
Hot:
var pub = new Component().AsObservable().Publish();
pub.Subscribe(_ => Console.WriteLine("Sub1"));
pub.Subscribe(_ => Console.WriteLine("Sub2"));
pub.Connect(); // started just once per two subscriptions
Composable:
new Component().AsObservable().Delay(TimeSpan.FromSeconds(1));
etc...
EDIT: For the case of multiple events that you have to wait on and collect information,
the following variation could be used:
public static IObservable<EventArgs> AsObservable(this Component component)
{
return Observable.Defer(() =>
{
component.BeginStart();
return
Observable.FromEvent<EventArgs>(component, "Started1").Take(1)
.Merge(
Observable.FromEvent<EventArgs>(component, "Started2").Take(1))
.Select(evt => evt.EventArgs);
});
}
With this one, if you want to block till completion, you might use .AsObservable.Last().
Something like this should do it:
var replay = Observable
.FromEvent<EventArgs>(this.component, "Started")
.Replay();
replay.Connect();
component.BeginStart();
replay.First();

Categories