subject.Dispose() vs subject.OnCompleted() - c#

What's the difference between .Dispose() and .OnCompleted() call on a Subject ?
Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer useful anywhere on the code,

According to the documentation of the Subject<T>.Dispose method:
Releases all resources used by the current instance of the Subject<T> class and unsubscribe all observers.
It seems that attempting to do anything with a Subject after disposing it, results to an ObjectDisposedException. You can't Subscribe to a disposed Subject for example. Any subscriptions that are active at the time the Subject is disposed, will be disposed too, and the unsubscribed observers will not receive OnCompleted notifications.
On the contrary a subject that has been completed by calling its OnCompleted method can still be subscribed at any time, in which case the subscribed observer will receive instantly an OnCompleted notification. Of course if the completed subject is one of the buffered types like the ReplaySubject, then the observers will receive a number of OnNext notifications before the final OnCompleted.
Personally I would consider calling Dispose to a ReplaySubject that is about to be discarded, in order to accelerate the recovery of the RAM used by its internal buffer. I am not sure if this would make any difference though, since the Dispose is generally supposed to release unmanaged resources, and the memory used by the buffer is most probably managed.

Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer usefull[sic] anywhere on the code
I think you have those backwards. I'm not familiar with rx.net, but I do know the IDisposable and Observable patterns. IDisposable is used to release resources from an object when you are completely done with it and it's no longer useful. OnCompleted is for when you are done observing (the provider has finished sending notifications), even if the object might still have other uses.

There is a very important semantic difference between calling .Dispose() and .OnCompleted() on a subject.
Consider this code:
Subject<int> subject = new Subject<int>();
IObservable<int[]> query = subject.ToArray();
IDisposable subscription =
query
.Subscribe(xs => Console.WriteLine(String.Concat(xs)));
subject.OnNext(1);
subject.OnNext(2);
If I then call subject.OnCompleted() I get 12 written to the Console. If, however, I call subject.Dispose() then nothing gets printed.
Some operators, like .ToArray() in my example code, expect the .OnCompleted() call to produce any value.
It is important to understand what queries you are performing on the subject to know how to end it properly - there are situations where both ways are valid.
I feel, though, that you are doing the right things with disposing of subscriptions and completing subjects.

Related

C# Reactive Extensions - Should I return a disposable?

I'm trying to understand when is a good time to return a disposable in the function passed to Observable.Create vs just disposing any resources through scope by a using statement.
Is returning the disposable more for cases where the Observable is an infinite stream? Even if so I don't understand how the using block won't still dispose the resource even if the stream is closed prematurely
I think the Disposable interface on the Observable paradigm is used solely for the purpose of getting rid of the subscription (i.e, stopping the callback on the observed events), as Theodor Zoulias pointed out. It doesn't manage any resources on the stream whatsoever. You might be confusing the use of the Disposable interface on other scenarios.
As regards to disposing subscriptions:
One of the use cases I can see for returning a Disposable is when when you have more than one to call the function on: supposing you had a list of Observables, you could iterate on it and call the function .Dispose() to cancel multiple subscriptions at once.
You could also pass that stream as a disposable to another Observable, to be disposed when some event occurs. Since the entire RX paradigm is about not knowing when things will be executed, this is interesting. I worked at an application where I had to cancel a subscription if a certain event happened, and I passed the Observable Subscription (IDisposable) to the Observer of such event/stream.
Something on these lines:
IDisposable subscription1 = observableOne.Subscribe(_ => # code omitted);
observableTwo.Subscribe(_ => {
subscription1?.Dispose();
subscription1 = null;
});
As Enigmaticy has pointed out, although this exemplifies my point, a better way to accomplish this would be:
observableOne.TakeUntil(observableTwo).Subscribe(_ => #code ommited);
I haven't worked with C# in a while but these are the use cases I can see on using vs Disposable as object. It gives you greater flexibility on when you want to cancel your subscriptons :~
Thanks to everyone responding in this post it's helped me understand a bit better. I've had a lot of stumbling in my understanding of RX and I think a lot of this just comes down to limited documentation and seems like many people online don't quite understand perfectly either so there's a lot of misinformation to sort through.
This other answer does the trick for me
https://stackoverflow.com/a/7707768/7183974 .
What it really comes down to is for when we have non-blocking code in our Observable.Create method. So when our observable is subscribed to we instantly return a disposable that can clean up any asynchronous / concurrent processes in the event that we need to cancel a subscription early.
This is necessary for cases where maybe your observable is using other async (push-based) code.
For iterative (pull-based) code that you simply want to be push based then you can use Observable.Create but TBH I think just using an Iterator is better and if you need it to be a push-based API then just use ToObservable.
I was trying to implement a push-based iterator so the disposable seemed redundant to me which is what confused me. I've since refactored my code to be pull-based and if I ever were to need it to be push-based again I would just use ToObservable.

Am I obliged to call EndPeek after using BeginPeek?

I have a Windows service that processes a private, local message queue (MSMQ). When it starts, it registers an event handler for PeekCompleted on the queue, and it then calls the asynchronous BeginPeek() to wait for a message to arrive.
protected override void OnStart(string[] args)
{
if (String.IsNullOrWhiteSpace(args[0]))
return;
queue = new MessageQueue(args[0]);
queue.Formatter = new BinaryMessageFormatter();
queue.PeekCompleted += new PeekCompletedEventHandler(OnPeekCompleted);
queue.BeginPeek();
}
Once a message arrives, my goal is to obviously process that message. My code currently has a queue.Receive() method to get the message, contained within a transaction so the message gets put back on the queue in case of errors during processing. BeginPeek() is called again to restart the cycle.
private static void OnPeekCompleted(Object source, PeekCompletedEventArgs asyncResult)
{
try
{
MessageQueue q = (MessageQueue)source;
using (MessageQueueTransaction trans = new MessageQueueTransaction())
{
trans.Begin();
Message msg = q.Receive(trans);
ProcessMessage(msg);
trans.Commit();
}
// Restart the asynchronous peek operation.
q.BeginPeek();
}
catch (MessageQueueException qEx)
{
// TODO: Walk it off.
}
return;
}
Do I, at any point, need to call EndPeek() on the queue ?
Maybe to avoid memory leaks, like this question alludes to ? I'm pretty sure I don't have to, but the documentation isn't very clear on that. It just doesn't feel 100% right to 'begin' something without 'ending' it :)
Btw: I could replace the Receive() line with Message msg = q.EndPeek(asyncResult.AsyncResult), which equally fetches me the message, but it doesn't remove the message from the queue.
Giving a proper answer to this question takes some effort, because the short answer ("no") could be misleading.
Does the API description explicitly say you must call EndPeek() for every call to BeginPeek()? Not in any topic I could find, and not only that, it appears to state the opposite here:
To use BeginPeek, create an event handler that processes the results
of the asynchronous operation, and associate it with your event
delegate. BeginPeek initiates an asynchronous peek operation; the
MessageQueue is notified, through the raising of the PeekCompleted
event, when a message arrives in the queue. The MessageQueue can then
access the message by calling EndPeek(IAsyncResult) or by retrieving
the result using the PeekCompletedEventArgs.
(Emphasis mine.) This seems to say that you can either use .EndPeek() or just directly get the message from the event args with no obligation to call .EndPeek().
Alright, so does the implementation mandate that you call .EndPeek() in order to make things work correctly? At least for the System.Messaging implementation in .NET 4.0, the answer is no. When you call .BeginPeek(), an asynchronous operation is allocated and a callback is registered for completion. The unmanaged resources associated with this operation are partially cleaned up in this callback, and only then is the event handler called. .EndPeek() does not actually do any cleanup -- it merely waits for the operation to complete if it hasn't yet, checks for errors, and returns the message. So it is indeed true that you can either call .EndPeek() or just access the message from the event args, or do nothing at all -- it will all work just as poorly.
Poorly, yes -- note that I said "partially cleaned up". The implementation of MessageQueue has a problem in that it allocates a ManualResetEvent for every asynchronous operation, but never disposes it, leaving this entirely up to the garbage collector -- something .NET developers are often excoriated for doing, but of course Microsoft's own developers aren't perfect either. I haven't tested whether the OverlappedData leak described in this question is still relevant, nor is it immediately obvious from the source, but it would not surprise me.
The API has other warning signs that its implementation may leave something to be desired, most prominently that it does not follow the established .Begin...() / .End...() pattern for asynchronous operations but introduces event handlers in the middle, producing a strange hybrid I've never see anywhere else. Then there's the very dubious decision of making the Message class inherit from Component, which adds considerable overhead to every instance and raises the question of when and how it should be disposed... all in all, not Microsoft's best work.
Now, does all this mean you're not "obliged" to call .EndPeek()? Yes, in the sense that calling it or not calling it makes no functional difference with regards to resource cleanup or correctness. But with all that said, my advice is still to call it anyway. Why? Because anyone who is familiar with how the asynchronous operation pattern works in other .NET classes would expect the call to be there, and not putting it there looks like a bug that could lead to resource leaks. If there is a problem with the application, such a person might reasonably spend some fruitless effort looking at "problem code" that isn't. Given that a call to .EndPeek() has negligible overhead compared to the rest of the machinery, I'd say the savings in programmer surprise more than make up for the costs. A possible alternative is to insert a comment instead, explaining why you're not calling .EndPeek() -- but in all probability this still takes more programmer cycles to grasp than just calling it.
In theory, another reason for calling it is that the semantics of the API could change in the future to make the call to .EndPeek() necessary; in practice, this is very unlikely to happen because Microsoft is traditionally reluctant to make breaking changes like this (code that previously and reasonably did not call .EndPeek() would stop working) and the existing implementation already contravenes established practice.

TestScheduler-created ColdObserver not unsubscribing when OnCompleted?

I wanted to check that an IObservable I had created was respecting the courtesy of "Once I've completed, I'll unsubscribe you". At first blush it looked like something was wrong with my code. But eliminating my code, and just using the Observable and Observer provided by TestScheduler, it looks like the 'unsubscription' never happens:
using Microsoft.Reactive.Testing;
using System.Reactive;
...
var ts = new TestScheduler();
var ob = ts.CreateObserver<int>();
var xs = ts.CreateColdObservable<int>(
new Recorded<Notification<int>>(1, Notification.CreateOnCompleted<int>())
);
xs.Subscribe(ob);
ts.AdvanceTo(2);
Assert.Equal(1, xs.Subscriptions.Single().Unsubscribe); //<-- Xunit no like
I originally suspected the observer, but I tried that on a variant of the code found here, and it works, so now I'm thinking that the implementation of Subscribe on the ColdObservable isn't behaving properly.
No such courtesy exists. The RX design guideines in section 4.3 suggest you can:
Assume resources are cleaned up after an OnError or OnCompleted message.
And in section 4.4 say you can:
Assume a best effort to stop all outstanding work on Unsubscribe
These guidelines ("courtesies") talk about an operator releasing it's own resources plus those of any it has acquired as soon as possible.
In your code, you aren't testing for either of these scenarios. The purpose of the Unsubscribe property on an ITestableObservable is to report when a subscription taken out by an observer was explicitly disposed, not when internal cleanup happened - but you are not storing this handle to be able to dispose it:
xs.Subscribe(ob); /* return of handle ignored here */
So you are trying to assert that you disposed the subscription you threw away, not that the observable you subscribed to cleaned up any subscription and resources it may have taken out.
If you want to see the effect of the timely resource clean up of 4.3/4.4, write an extension method like this:
public static IObservable<T> SpyResourceCleanUp<T>(
this IObservable<T> source, IScheduler scheduler)
{
return Observable.Create<T>(obs =>
{
var subscription = source.Subscribe(obs);
return new CompositeDisposable(
subscription,
Disposable.Create(() => Console.WriteLine(
"Clean up performed at " + scheduler.Now.Ticks)));
});
}
And replace your line:
xs.Subscribe(ob);
with
xs.SpyResourceCleanUp(ts).Subscribe(ob);
(Editing in some of the comments)
On your test I see immediate resource clean-up, as I would expect. And with this change your test will now pass because SpyResourceCleanUp is unsubscribing from it's parent (xs) as soon as it OnCompletes() itself in adherence to 4.3 of the guidelines.
What might not be obvious here is that Observable.Create handles calling the Dispose() method of the returned IDisposable as soon as either the subscription is disposed or OnComplete() or OnError() has been called on the observer. This is how Create helps you implement section 4.3, and why the test passes with the altered code.
Under the covers, subscriptions to the AnonymousObservable<T> : ObservableBase<T> returned by Create are wrapped by an AutoDetachObserver as you can see here.
i.e. The Disposable you return from Observable.Create isn't the one the caller gets - they get a wrapped version that will call your Dispose() either on stream termination or cancellation.

What to do with IObservers being disposed?

I'm using Reactive Extensions for easy event handling in my ViewModels (Silverlight and/or Wp7 apps). For sake of simplicity let's say I have a line like this in the ctor of my VM:
Observable.FromEvent<PropertyChangedEventArgs>(
h => MyObject.PropertyChanged += h,
h => MyObject.PropertyChanged -= h)
.Where(e=>e.PropertyName == "Title")
.Throttle(TimeSpan.FromSeconds(0.5))
.Subscribe(e=>{/*do something*/});
this returns an IDisposable object, which if disposed will unsubscribe. (Am I right in this assumption?)
If I hold no reference to it, sooner or later it will be collected, and my handler will be unsubscribed.
I usually have a List<IDisposable> in my VM, and I add subscriptions to it, yet I feel dirty about it, as if I'm not doing something in a correct Rx way.
What is the best practice, recommended pattern on situations like this?
Your first assumption is correct, the IDisposable is for unsubscribing. However, you do not need to hold a reference to the IDisposable to prevent your observer from being collected. The IObservable will need to keep a reference to the observer to be able to call its methods, thus keeping the observer alive as long as the observable is alive.
The astute reader will realize that I am somewhat begging the question, because I have assumed that the observable will not be collected. To deal with that issue, let's make some reasonable guesses about what's going on behind the scenes. The first observable is subscribing to an event. This means that the object with the event has a reference to our observer from the time we subscribe to the time we unsubscribe. Since Rx operators must at some point subscribe to their sources, one can assume that the event observer has a reference to the Where observer, which has a reference to the Throttle observer, which of course is referring to our final observer.
Since we kept no way to unsubscribe, this ties the life of the observer to the life of the object with the event. Without full knowledge of your program, that is all the farther up the chain I can go, but I think it should be sufficient for you to determine the lifetime of the observable.
This actually points out a potential "memory leak" that you can have with standard .NET events, objects keeping all their event subscribers alive, which leads to your second question. If you do not keep a reference to the IDisposable, you will never be able to unsubscribe from the event and your object will continue to receive notices, even after you close the view it is related to. If the event source does not live longer than the view, this may not be a problem, but I recommend using the disposable.
There is nothing "un-Rx" about this, and Rx even includes a nice class to use as an alternative to the List if you want, System.Reactive.Disposables.CompositeDisposable.
Gideon is incorrect here. The semantics of how Rx use IDisposable are different than typical .NET. The IDisposable returned from Subscribe is if you want to unsubscribe earlier than the end of the IObservable. If you don't want to do this, complicating your code with all of the extra disposable management is unnecessary.
Common practice is to implement IDisposable interface and dispose your disposable members here.

Finalizers accessing managed stuff

I am well aware that finalizers are typically used to control unmanaged resources. Under what circumstances may a finalizer deal with managed ones?
My understanding is that presence in the finalizer queue will prevent any object, or objects strongly referenced thereby, from being collected, but it will not (of course) protect them from finalization. In the normal course of events, once an object is finalized it will be removed from the queue and any objects it references will no longer be protected from collection on the next GC pass. By the time a finalizer is called, the finalizers may have been called for any combination of objects referred to by the object; one cannot rely upon finalizers being called in any particular sequence, but the object references one holds should still be valid.
It's pretty clear that a finalizer must never acquire locks, nor attempt to create a new object. Suppose, however, that I have an object that subscribes to some events, and another object which actually uses the events. If the latter object becomes eligible for garbage collection I want to have the former object unsubscribe from events as soon as practical. Note that the former object will never become eligible for finalization until no subscriptions for it are held by any live object.
Would it be practical to have a lock-free linked-list stack or queue of objects which needed to be unsubscribed, and have the main object's finalizer put a reference to the other object on the stack/queue? The linked-list item object would have to be allocated when the main object was created (since allocation within the finalizer would be forbidden), and it would probably be necessary to use something like a timer event to poll the queue (since the event unsubscription would have to run outside the finalizer thread, and it would probably be silly to have a thread whose sole purpose was to wait for something to appear on the finalizer queue), but if the finalizer could safely reference its pre-allocated linked-list object and the main queue object associated with its class, it could allow the events to be unsubscribed within 15 seconds or so of finalization.
Would that be a good idea? (Notes: I'm using .net 2.0; also, an attempt to add to the stack or queue might spin a few times on Threading.Interlocked.CompareExchange, but I wouldn't expect that it should ever be stuck very long).
EDIT
Certainly any code which subscribes events should implement iDisposable, but disposable things aren't always disposed properly. If there were, there wouldn't be any need for finalizers.
My scenario of concern would be something like the following: a class implementing iEnumerator(of T) hooks onto a changeNotify event of its associated class so that an enumeration can be sensibly handled if the underlying class changes (yes, I know Microsoft thinks all enumerators should simply give up, but sometimes an enumerator which can keep working will be more useful). It's quite possible that an instance of the class might be enumerated many thousands or even millions of times over the course of days or weeks, but not be updated at all during that time.
Ideally, the enumerator would never be forgotten about without being disposed, but enumerators are sometimes used in contexts where "foreach" and "using" aren't applicable (e.g. some enumerators support nested enumeration). A carefully-designed finalizer might allow a means to deal with this scenario.
Incidentally, I'd require that any enumeration which is supposed to continue through updates must use the generic IEnumerable(of T); the non-generic form, which doesn't handle iDisposable, would have to throw an exception if the collection gets modified.
Suppose, however, that I have an object that subscribes to some events, and another object which actually uses the events. If the latter object becomes eligible for garbage collection I want to have the former object unsubscribe from events as soon as practical. Note that the former object will never become eligible for finalization until no subscriptions for it are held by any live object.
If the "latter object" is the one that's using the events, and the "former" object is the one subscribing to the events, the "former" object has to have some way to pass the event info to the "latter" object - meaning it's going to have some reference in place to "latter". Chances are, this will keep the "latter" object from ever being a GC candidate.
That being said, I would recommend avoid this type of managed resource deallocation via the finalizer, unless absolutely necessary. The architecture you're describing seems very fragile, and very tricky to get right. This is probably a better candidate for IDisposable, with the finalizer being the "last ditch" cleanup effort.
Although IDisposable is typically about releasing native resources - it can be about releasing any resource, including your subscription information.
Also, I'd try to avoid having a single global collection of object references - it might make more sense to have your objects internally just use a WeakReference. As soon as the "latter" object is collected, the "former" object's WeakReference would no longer be valid. The next time an event subscription is raised, if the internal WeakReference is no longer valid, you can just unsubscribe yourself. No need for global queues, lists, etc - it should just work...
I'm going to call the objects "publisher" and "subscriber" and restate my understanding of the problem:
In C#, the publisher will (effectively) hold references to the subscribers, preventing subscribers from being garbage collected. What can I do so that the subscriber objects can be garbage collected without explicitly managing the subscriptions?
First, I would recommend doing everything I could to avoid this situation in the first place. Now, I'm going to move on and assume you have, considering you're posting the question anyway =)
Next, I would recommend hooking the add and remove accessors of the publisher's event(s) and using a collection of WeakReferences. You can then automatically unhook those subscriptions whenever the event is invoked. Here's an extremely rough, untested example:
private List<WeakReference> _eventRefs = new List<WeakReference>();
public event EventHandler SomeEvent
{
add
{
_eventRefs.Add(new WeakReference(value));
}
remove
{
for (int i = 0; i < _eventRefs; i++)
{
var wRef = _eventRefs[i];
if (!wRef.IsAlive)
{
_eventRefs.RemoveAt(i);
i--;
continue;
}
var handler = wRef.Target as EventHandler;
if (object.ReferenceEquals(handler, value))
{
_eventRefs.RemoveAt(i);
i--;
continue;
}
}
}
}
Let me make sure I understand -- are you worried about leaks from event subscribers that remain subscribed to a collected event publisher?
If that's the case, then I don't think you have to worry about it.
Here's what I mean assuming that the "former" object is the event subscriber and the "latter" object is the event publisher (raises the event):
The only reason that the subscriber (former) is "subscribed" is because you created a delegate object and passed that delegate to the publisher ("latter").
If you look at the delegate members, it has a reference to the subscriber object and to the method on the subscriber that will be executed. So there is a reference chain that looks like this: publisher --> delegate --> subscriber (publisher references delegate, which references subscriber). It's a 1-way chain -- the subscriber does not hold a reference to delegate.
So, the only root that keeps the delegate around is on the publisher ("latter"). When latter becomes eligible for GC, so does the delegate. Unless there is some special action you want for your subscribers to take when they unsubscribe, they will effectively become unsubscribed when the delegate gets collected -- there is no leak).
Edit
Based on supercat's comments, it sounds like the problem is that the publisher is keeping the subscriber alive.
If that's the problem, then finalizers won't help you. Reason: Your publisher has a real, bonafide reference to your subscriber (via the delegate), and the publisher is rooted (otherise it would be eligible for GC), so your subscribers are rooted, and will not be eligible for finalization or GC.
If you are having trouble with publisher keeping subscriber alive, I would suggest that you search for weak-ref events. Here are a couple links to get you started: http://www.codeproject.com/KB/cs/WeakEvents.aspx http://www.codeproject.com/KB/architecture/observable_property_patte.aspx.
I had to deal with this once as well. Most of the effective patterns involve changing the publisher so that it holds a weak-ref to the delegate. Then you have a new problem -- the delegate isn't rooted, and you hvae to keep it alive somehow. The articles above probably do something like that. Some techniques use reflection.
I used a technique once that did not rely upon reflection. It required that you be able to make changes to the code in both the publisher and the subscriber, though. If you would like to see a sample of that solution, let me know.
Let's try this again. Can you add your event handlers to your publisher like this:
var pub = new Publisher();
var sub = new Subscriber();
var ref = new WeakReference(sub);
EventHandler handler = null; // gotta do this for self-referencing anonymous delegate
handler = (o,e) =>
{
if(!ref.IsAlive)
{
pub.SomeEvent -= handler; // note the self-reference here, see comment above
return;
}
((Subscriber)ref.Target).DoHandleEvent();
};
pub.SomeEvent += handler;
This way, your delegate doesn't keep a direct reference to the subscriber, and automatically unhooks itself whenever the subscriber gets collected. You could implement this as a private static member of the Subscriber class (for the purposes of encapsulation), just make sure it's static to prevent inadvertently holding onto a direct reference to the "this" object.

Categories