I am at the early stages of learning about Rx and have come across the Subject class. I don't quite understand why this class exists. I understand that it implements both IObservable and IObserver but what are Subjects used for?
As far as I can tell, they can act as a proxy between a source and a bunch of subscribers but couldn't the subscribers just subscribe directly to the source? When I see instances of a Subject being used as an observable and observer I get confused.
I am sure I am just not getting some basic fact here but I don't know what Subject brings to the game. I guess I am looking for some basic (but hopefully real world) example of when Subjects are useful and when they are not (as I have also read that Subjects are not usually used, replaced with Observable.Create).
First, a lot of folks will tell you Subject<T> doesn't belong, since it goes against some other tenets/patterns in the Rx framework.
That said, they act as either an IObservable or an IObserver, so you get some useful functionality out of them - I generally use them during the initial development stages for:
A "debug point" of sorts, where I can subscribe to an IObservable chain inline with a Subject<T>, and inspect the contents with the debugger.
An "observable on demand", where I can manually call OnNext and pass in data I want to inject into the stream
Used to use them to replicate what ConnectableObserable now does - a "broadcast" mechanism for multiple subscribers to a single Observable, but that can be done with Publish now.
Bridging layer between disparate systems; again, this is largely unnecessary now with the various FromAsync, FromEvent extensions, but they can still be used as such (basically, the "old" system injects events into the Subject<T> via OnNext, and from then on the normal Rx flow.
Using subjects means we are now managing state, which is potentially mutating. Mutating state and asynchronous programming are very hard to get right. Furthermore many of the operators (extension methods) have been carefully written to ensure correct and consistent lifetime of subscriptions and sequences are maintained. When you introduce subjects you can break this.
A significant benefit that the Create method has over subjects is that the sequence will be lazily evaluated.
In this example we show how we might first return a sequence via standard blocking eagerly evaluated call, and then we show the correct way to return an observable sequence without blocking by lazy evaluation.
Below example will be blocked for at least 1 second before they even receive the IObservable, regardless of if they do actually subscribe to it or not.
private IObservable<string> BlockingMethod()
{
var subject = new ReplaySubject<string>();
subject.OnNext("a");
subject.OnNext("b");
subject.OnCompleted();
Thread.Sleep(1000);
return subject;
}
Where as in bleow example consumer immediately receives the IObservable and will only incur the cost of the thread sleep if they subscribe.
private IObservable<string> NonBlocking()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
observer.OnNext("a");
observer.OnNext("b");
observer.OnCompleted();
Thread.Sleep(1000);
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
//or can return an Action like
//return () => Console.WriteLine("Observer has unsubscribed");
});
}
Related
I am trying to learn how to work with Zenject's and unity and I have encountered a particular problem that I do not know if it has a possible solution solely using Zenject's api.
Let assume i have MethodA, MethodB and MethodC, and a SignalA.
Is it possible to make this sequence:
SignalA.Fire() => MethodA (until released/finished)
=> MethodB (until released/finished)
=> MethodC (until released/finished)
Right now i have this pice of code :
private void BindSignalA()
{
Container.DeclareSignal<SignalA>().RunSync();
Container.BindSignal<SignalA>().ToMethod<MethodA>(handler => handler.Execute).FromNew();
Container.BindSignal<SignalA>().ToMethod<MethodB>(handler => handler.Execute).FromNew();
Container.BindSignal<SignalA>().ToMethod<MethodC>(handler => handler.Execute).FromNew();
}
And MethodA looks like this :
public class MethodA
{
public async void Execute()
{
await new WaitUntil(() => false);
}
}
So the expected result is that MethodB and MethodC will be never executed.
But the actual result is that all Methods are executed.
Is there a solution using Zenject's api to make this happen?
Thanks for the help, and in case any more information is needed I would love to know.
I am not familiar with signals, but checking the documentation , mainly the the 3rd point into consideration maybe your case is not good scenario for signal use.
When To Use Signals
Signals are most appropriate as a communication mechanism when:
There might be multiple interested receivers listening to the signal
The sender doesn't need to get a result back from the receiver
The sender doesn't even really care if it gets received. In other words, the sender should not rely on some state changing when the signal is called for subsequent sender logic to work correctly. Ideally signals can be thought as "fire and forget" events
The sender triggers the signal infrequently or at unpredictable times
On the other hand I you might be confusing decoupling the code with the syncronous execution concept. Delegates or events (which are a specific type of delegate) are spare pieces of logic of one class that you can keep so that can be executed in other class, so that you can "subscribe" or "listen" to something that might happen to execute/invoke your event in other part of the code. However that does not involve any asyncronous code or multithreading.
As far as I can guess, signals are used to handle event subscription/invocation in a decoupled manner with the Zenject signal object, in a similar way as dependencies between classes are handled in a decoupled manner with interfaces, so first I would check if your case is suitable for their use checking the documentation carefully and following the examples provided along until the concept clicks.
Meanwhile, I would first try to use c# normal delegates so that after the zenject signal misson can be understood. Also providing a simple working example of what you are trying to do without zenject would be very helpful as departing point to achieve the zenject way of achieving that same thing.
I was talking to a colleague who pointed me to the SO question about subjects being considered harmful. However, I have two cases where I have some non-deterministic code that does not seem reasonable any other way.
Non-standard event:
event handler(class, result)
{
subject.OnNext(result);
}
public delegate void _handler
([MarshalAs(UnmanagedType.Interface), In] MyClass class,
[MarshalAs(UnmanagedType.Interface), In] ResultClass result)
Parallel Tasks (Non-Deterministic number of tasks all running in parallel, starting at different times):
Task.Start(()=> ...).ContinueWith(prevTask => subject.OnNext(prevTask.result))
The subject is not exposed, only through an observable. Is there another route suggested that isnt a ton of boilerplate?
Subjects are not always harmful. There are many legitimate uses of them even within Rx itself. However, many times a person goes to use a Subject, there's already a robust Rx method written for that scenario(and it may or may not be using subjects internally). This is the case for your 2 examples. Look at Task.ToObservable and Observable.FromEventPattern.
Another common case subjects are misused is when a developer breaks a stream in two. They become convinced they need to subscribe to a stream and in the callback they produce data for a new stream. They do this with a Subject. But usually they just should have used Select instead.
Observable.FromEvent
System.FromEvent works for more than just built-in event types: you just need to use the correct overload.
class Program
{
private static event Action<int> MyEvent;
public static void Main(string[] args)
{
Observable.FromEvent<int>(
(handler) => Program.MyEvent += handler,
(handler) => Program.MyEvent -= handler
)
.Subscribe(Console.WriteLine);
Program.MyEvent(5);
Console.ReadLine();
}
}
Task.ToObservable & Merge
If you already have access to all of your tasks, you can convert them to Observables, and Merge them into a single observable.
class Program
{
public static void Main(string[] args)
{
Observable.Merge(
// Async / Await
(
(Func<Task<string>>)
(async () => { await Task.Delay(250); return "async await"; })
)().ToObservable(),
// FromResult
Task.FromResult("FromResult").ToObservable(),
// Run
Task.Run(() => "Run").ToObservable()
)
.Subscribe(Console.WriteLine);
Console.ReadLine();
}
}
Merge Observable
Alternatively, if you do not have all of your tasks up front, you can still use Merge, but you'll need some way of communicating future tasks. In this case, I've used a subject, but you should use the simplest Observable possible to express this. If that's a subject, then by all means, use a subject.
class Program
{
public static void Main(string[] args)
{
// We use a subject here since we don't have all of the tasks yet.
var tasks = new Subject<Task<string>>();
// Make up some tasks.
var fromResult = Task.FromResult("FromResult");
var run = Task.Run(() => "Run");
Func<Task<string>> asyncAwait = async () => {
await Task.Delay(250);
return "async await";
};
// Merge any future Tasks into an observable, and subscribe.
tasks.Merge().Subscribe(Console.WriteLine);
// Send tasks.
tasks.OnNext(fromResult);
tasks.OnNext(run);
tasks.OnNext(asyncAwait());
Console.ReadLine();
}
}
Subjects
Why to use or not to use Subjects is a question I don't have the time to answer adequately. Typically speaking, however, I find that using a Subject tends to be the "easy way out" when it appears an operator does not already exist.
If you can somehow limit the exposure of a subject in terms of it's visibility to the rest of the application, then by all means use a subject and do so. If you're looking for message bus functionality, however, you should rethink the design of the application, as message buses are anti-patterns.
Subjects aren't harmful. That is probably even a little too dogmatic for me (and I am first to boo-boo the use of subjects). I would say that Subjects indicate a code smell. You probably could be doing it better without them, but if you keep the encapsulated within your class then at least you keep the smell in one place.
Here I would say, that you are already using "non-standard" event patterns, and it seems you don't want to, or cant, change that. In this case, it seems the usage of subjects as a bridge isn't going to make it any worse than it is.
If you were starting from scratch, then I would suggest that you deeply think about your design and you will probably find that you just wouldn't need a subject.
Lastly, I agree with the other comments that you should be using a FromEvent and ToTask, but you suggest these do not work. Why? I dont think you provide nearly enough of your code base to help with design questions like this. e.g. How are thee nondeterministic task being created? and by what? What is the actual problem you are trying to solve. If you could provide a full example, you might get the amount of attention you are looking for.
Here is what a good book about the Rx says regarding why and when Subject can be harmful:
http://www.introtorx.com/Content/v1.0.10621.0/18_UsageGuidelines.html
"Avoid the use of the subject types. Rx is effectively a functional
programming paradigm. Using subjects means we are now managing state,
which is potentially mutating. Dealing with both mutating state and
asynchronous programming at the same time is very hard to get right.
Furthermore, many of the operators (extension methods) have been
carefully written to ensure that correct and consistent lifetime of
subscriptions and sequences is maintained; when you introduce
subjects, you can break this. Future releases may also see significant
performance degradation if you explicitly use subjects."
This is potentially a very stupid question, but I'm not sure if I should be holding on to the IObservables generated by the Linq extension methods. Most of the examples seem to do so by default, but what would happen in a long running program. I have two examples to explain my question:
My first, and currently default implementation, involves subscribing to an IObservable provided by a pub\sub event aggregator. I'm comfortable with this because I know the observable will be around as long as the aggregator is.
protected virtual void SubscribeToEvents()
{
_subscriptions.Dispose();
_subscriptions = new CompositeDisposable();
IDisposable sendSubscription = Events.GetStream<OutgoingByteMessage>()
.Subscribe(msg =>
{
if (msg.Identifier.ChannelId == this.Id)
{
var queueItem = Tuple.Create(msg.Identifier.ConnectionId, msg.Data);
_sendQueue.Enqueue(queueItem);
}
});
_subscriptions.Add(sendSubscription);
}
However, if I use Linq to break down some of that logic, I can do this to get a subscription:
IDisposable altSendSubscription = Events.GetStream<OutgoingByteMessage>()
.Where(msg => msg.Identifier.ChannelId == this.Id)
.Select(msg => Tuple.Create(msg.Identifier.ConnectionId, msg.Data))
.Subscribe(item =>
{
_sendQueue.Enqueue(item);
});
My question is, on that second version, should I be keeping the product of that .Select method? This is happening in a method, afterall, so technically wouldn't the IObservable being returned there go out of scope as soon as SubscribeToEvents complete and be eligible for garbage collection? Or does the IDisposable object itself keep a reference to it, thereby making it safe to not keep a concrete reference to it somewhere.
After looking at the Rx source it looks like they use a series of forwarder classes to accomplish the Linq magic but I'm still a little paranoid. What do you guys think?
At the end of the day, all of the IObservable objects are being held via the list of subscribers on Events.GetStream (depending on your implementation of Events.GetStream, of course). Whether this goes out of scope depends on your implementation.
However, holding the IDisposable almost certainly keeps the subscription in scope as well, so even if your implementation was return Observable.Never<OutgoingByteMessage>, it would still exist because of the IDisposable.
You usually don't have to worry about active subscriptions going out of scope - the thing you should worry instead about is, subscription leaks. These occur when you subscribe to a global object (like something returned from an IoC container) and don't disconnect the subscription (and if the Observable never terminates).
This sounds like it'd not happen often, but it comes up more than you'd expect. For example:
MessageBus.Current.Listen<FooMessage>()
.Where(x => x.Bar == "Baz")
.Subscribe(x => Console.WriteLine(x));
If I put that in a constructor of some object that gets created all the time, I create dozens of subscriptions that never get cleaned up.
No, you do not need to worry. Think about it like this: as long as there is a source of events, the observable chain cannot be collectable since the act of subscribing links them all together. That is, each operator subscribes to the one above creating an observer it's parent references.
You don't even need to hold on to the subscription handle (altSendSubscription).
Why not use a memory profiler and look at the heap to convince yourself?
Reading msdn about the Reactive Extensions and such, I've found a recommendation saying I shouldn't implement IObservable, rather use Observable.Create... By the time I've read this, my project already had an ObservableImplementation<T> class, which I'd used as an IObservable source, everywhere I wanted to transform events into Observables.
I've read the AbstractObservable<T> implementation in System.Reactive, and I haven't found any major difference between their code and mine. So what's wrong with implementing IObservable? I can add my own properties to it, and so on...
for fullness sake, here is my implementation, please tell me if I did anything wrong!
public sealed class ObservableImplementation<T> : IObservable<T>
{
class Subscription : IDisposable
{
private readonly Action _onDispose;
public Subscription(Action onDispose)
{
_onDispose = onDispose;
}
public void Dispose()
{
_onDispose();
}
}
public void Raise(T value)
{
_observers.ForEach(o => o.OnNext(value));
}
public void Completion()
{
_observers.ForEach(o => o.OnCompleted());
_observers.Clear();
}
private readonly List<IObserver<T>> _observers = new List<IObserver<T>>();
public IDisposable Subscribe(IObserver<T> observer)
{
var subscription = new Subscription(() => _observers.Remove(observer));
_observers.Add(observer);
return subscription;
}
public bool AnyObserverPresent { get { return _observers.Any(); } }
}
There are a few reasons why we don't recommend people to implement IObservable<T> directly.
One is the lack of protection against violations of the observer grammar. For example, your sequence can exhibit behavior of OnNext calls following an OnCompleted call, which is invalid. The Observable.Create<T> method and ObservableBase<T> base type take care of this, by automatically detaching the observer upon receiving a terminal message. So even if your code does the wrong thing, the observer is not seeing a malformed sequence.
Btw, this is similar to iterators in C#. Implementing IEnumerable<T> manually should be such that when an enumerator's MoveNext returns false (analogous to OnCompleted), subsequent calls don't change their mind and start returning true (analogous to OnNext):
If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext also return false until Reset is called. (Source: MSDN)
When using iterators in C# 2.0 or VB 11.0, such concerns are taken care of for you. This is similar to our Observable.Create<T> method and ObservableBase<T> base type.
A reason related to the discussion above is clean-up. Upon returning from a Dispose call on a subscription, will the observer no longer see any messages? Upon sending a terminal message into the observer, will the Dispose logic for the related subscription be called automatically? Both are non-trivial to get right, so our base implementation takes care of that.
Another reason has to do with our CurrentThreadScheduler, ensuring that Subscribe calls can be asynchronous when running on that scheduler. Essentially, we need to check whether we need to install a trampoline on the current thread during a call to Subscribe. We don't expect everyone to know about this and do the right thing.
In your particular case - as noticed by others here - you're building pretty much a subject. Either just use one of our subjects, or wrap it by containment in your own type (e.g. if you want the sending "observer" side to be accessible by other parties than the receiving "observable" side).
The reason you shouldn't implement IObservable<T> is the same reason you don't usually implement IEnumerable<T>, is that somebody has most likely already built the thing you want. In this case, you've basically reimplemented Subject<T> for the most part.
Edit: As to the Lazy question in the comments, I'd implement that this way:
var lazyObservable = Observable.Create<TFoo>(subj => { /*TODO: Implement Me to load from reflection*/ })
.Multicast(new Subject<TFoo>()) // This means it'll only calc once
.RefCount(); // This means it won't get created until someone Subscribes
A recent blog post from the Rx team contains three reasons. Because it is a lengthy post I have copied the relevant parts.
Enforce the contract
Observable.Create takes in a single delegate that will become the core
implementation of the Subscribe method on the resulting IObservable
implementation. We do some clever wrapping around this delegate to
enforce the observer contract, amongst other things (which is why you
shouldn’t implement the interface yourself).
Wrapper for disposable
The returned disposable has a little wrapper around it, used to ensure
the observer won’t be called anymore after returning from the Dispose
call, even though the scheduler may not be at a good stopping point
yet. (Yet another reason you should never implement the IObservable
interface by hand. Oh, and by the way, there’s even more!)
Auto dispose on completion
The point of interest here is the auto-dispose behavior that’s applied
to the source subscription upon sending the OnCompleted downstream.
(This is yet another reason why manual implementation of
IObservable is strongly discouraged. When using
Observable.Create, we take care of this for you.)
I wrote an implementation based on the examples at [ Rx DEVHOL202] and http : //rxwiki.wikidot.com/101samples#toc48
Here is my code. http://csharp.pastebin.com/pm2NAPx6
It works, but the calls to OnNext are not NonBlocking, which is what i would like to implement to simulate a network read and asynchronously handing off each chunk of bytes as it is read to a handler [ which is not shown here in full but might cache results and do further processing ].
What is a good way of doing that?
Once the Exception gets thrown, all the subsequent OnNext()s are not processed!!
If I dont explicitly exit the loop and indicate completion.
Why is this so?
I would strongly recommend against trying to implement your own IObservable. The implicit rules go beyond thread safety and into method call ordering.
Usually you would return IObservable instances from methods, but if you need a class that implements it directly, you should wrap a Subject:
public class SomeObservable<T> : IObservable<T>
{
private Subject<T> subject = new Subject<T>();
public IDisposable Subscribe(IObserver<T> observer)
{
return subject.Subscribe(observer);
}
}
1. You need to be careful about how you support this from your observer (as you may have shared data), but you can make your handling of the calls asynchronous in one of two ways:
Call ObserveOn(Scheduler.TaskPool) (or ThreadPool if you are pre-4.0) before you call Subscribe. This causes messages to be routed through a scheduler (in this case, a task)
Pass the IScheduler to the Observer constructor
Start an asynchronous task/thread from your subscriber
2. This is the expected functionality. The contract between IObservable and IObserver is (OnNext)* (OnCompleted | OnError)?, which is to say "zero or more calls to OnNext, optionally followed by EITHER OnCompleted or OnError". After OnCompleted|OnError, it is invalid to call OnNext.
All the operators in Rx (Where, Select, etc) enforce this rule, even if the source doesn't.
I'm not sure if I understand your question correctly, but why can't you just execute whatever logic you have on a different Thread, or if it's small enough push it on a ThreadPool?
Here is an example:
ThreadPool.QueueUserWorkItem(o=>
{
_paidSubj.OnNext(this); // Raise PAID event
});
I'm confused about the data type on Subject, I have never seen that class in C#... is it something that you created? Is OnNext an event that gets raised or is it just a method? If OnNext is an event, then you can use BeginInvoke to invoke it asynchronously:
_paidSubj.OnNext.BeginInvoke(this, null, null);
Update:
An important thing that will happen if you implement this kind of asynchronous behavior: if you notify an IObserver by passing the Order, you might actually have some inconsistencies when you try to read the data in the observer (namely the order buffer) while the Order continues to modify the buffer in its Read thread. So there are at least two ways to solve this:
Restrict access to the memory which will get modified by using locks.
Only notify the observer with the relevant information that you want it to see:
a. By passing the information as a value (not as a reference).
b. By creating an immutable structure that transmits the information.
P.S.
Where did you get Subject from? Is Subject supposed to be an OrderObserver?