How to know that DataTable is already subscribed to OnRowChanged or OnColumnChanged events ?
I am facing a issue with many notifications in my app ? so I wanted to put a check and want to subscribe table only once ??
Outside of the declaring class it is deliberately tricky to see what is subscribed, since that is generally not something you need to know.
Depending on the scenario, either get very good at tracking when you subscribe, or simply unsubscribe first (which does nothing if you aren't subscribed):
foo.OnSomeEvent -= SomeHandler;
foo.OnSomeEvent += SomeHandler;
As long as the handler and target-instance (for non-static handlers) is the same this will:
if subscribed, the net result is that you are still subscribed afterwards
if not subscribed, the net result is that you end up subscribed
Related
I have the following code to let the GUI respond to a change in the collection.
myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());
First of all is this a good way to do this?
Second: what's the code to unsubscribe from this event? Is it the same but with -= (and then the complete anonymous method again)?
First of all... yes its a good way of doing it, it's clean, small form and easy to read & understand... the caveat of course is "Unless you later want to unsubscribe".
I believe Jon Skeet pointed out before that
"the specification explicitly doesn't guarantee the behaviour either way when it comes to equivalence of delegates created with anonymous methods."
So if you need to unsubscribe from the event at a later time, you'd be best to actually create a delegate instance so you can hang onto the reference for later.
var myDelegate = delegate(sender, e){UpdateMyUI()};
myObservableCollection.CollectionChanged += myDelegate;
myObservableCollection.CollectionChanged -= myDelegate;
If you need to unsubscribe from an event, you need an instanced reference. Unfortunately, that means you can't use that particular syntax.
It's an ok way to go, unless myObservableCollection is going to live longer than 'this', in which case you could end up with a memory leak, as the delegate which is created behind the scenes will conserve a reference to your 'this', which will keep it alive. If you are repeatedly creating and 'destroying' whatever is listening to the event, you will find that they aren't being collected by the garbage collector.
If this is a problem, you can go the route suggested in the answers, conserving a reference to the handler, which you must create first.
Another solution is to use weak references to create an event handler which will allow the subscriber to be collected if there are not other references. I've explored this solution in this question and answer.
I guess C# eventhandler has a list of listeners and it loops thru the list when sending a message. My question is how does this works in internally. Does it make a copy of the list before looping it thru and if so, what happens if someone unregister itself after the list has been copied but it has not yet received the message.
Will it still get the message even do it has unregister itself?
A delegate is immutable, so when you are invoking a delegate the list of subscribers is known and fixed. Subscribing or unsubscribing replaces the delegate that underpins the event.
This does indeed mean that in a multi-threaded scenario you can receive an event after unsubscribing, because either:
the delegate was already in the process of being invoked
a snapshot of the delegate had already been obtained for the purpose of invoking
by 2, I mean the usual pattern (to prevent a null-ref during invoke):
var handler = SomeEvent;
// <===== another thread could unsubscribe at this point
if(handler != null) handler(sender, args); // <== or part way through this invoke
// (and it either case, have the event trigger even though they think they have
// unsubscribed)
For that reason, if you are coding complex multi-threaded code with events, you should code defensively such that the event firing after you think you have unsubscribed is not a problem.
These nuances do not really impact single-threaded code.
Say I have the following code:
public event EventHandler DatabaseInitialized = delegate {};
//a intederminant amount of subscribers have subscribed to this event...
// sometime later fire the event, then create a new event handler...
DatabaseInitialized(null,EventArgs.Empty);
//THIS LINE IS IN QUESTION
DatabaseInitialized = delegate {};
Will this clear out the subscribers, replacing it with new empty default? And, will the event notify all subscribers before they get cleared out? I.E. Is there a chance for a race condition?
Yes it will clear it out. And because events fire syncronously in the same thread there shouldn't be race condition.
My advice: when in doubt, write a small test application and... well, test it.
UPDATE: I tested it before posting. (In response to minuses.)
To unsubscribe from the event use event-=delegate, so you're sure that resource is free. Even if by official Microsoft documentation it's not necessary, in my own experience, especially on a large scale complex project, unnecessary events suscribers are source for memory leaks. So unsubscribe from them explicitly.
Following on from this post - what are the disadvantages when using the -= then += approach suggested when I only ever want one handler event to fire?
_value.PropertyChanged -= _handlerMethod;
_value.PropertyChanged += _handlerMethod;
This doesn't guarantee that there is only one handler fired.
Another location could, potentially, subscribe your handler to your event multiple times. In this case, you will only remove the first handler call.
By inspecting the invocation list of the event, you could guarantee this behavior, if you truly only want a single handler to be subscribed at a time.
If you really want only one handler to execute, then you may want to use a settable property of the appropriate delegate type instead of an event. Only one delegate will be stored; you can execute the delegate the same as you would the event handler.
The idea here is that the -= operator is not going to do anything if your event handler is not assigned.
I don't personally like this approach, I think you should really aim to refactor your code so that you know that the event handler is assigned only once.
The disadvantages would be:
- possibility of race condition, if your app is multithreaded and the event gets fired when the handler is not assigned
- I am also not sure what happens when you run _value.PropertyChanged -= _handlerMethod when two copies of the handler are already assigned.
- messy code - obviously its not clear from the code which class and when is listening to the event
I have the following code to let the GUI respond to a change in the collection.
myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());
First of all is this a good way to do this?
Second: what's the code to unsubscribe from this event? Is it the same but with -= (and then the complete anonymous method again)?
First of all... yes its a good way of doing it, it's clean, small form and easy to read & understand... the caveat of course is "Unless you later want to unsubscribe".
I believe Jon Skeet pointed out before that
"the specification explicitly doesn't guarantee the behaviour either way when it comes to equivalence of delegates created with anonymous methods."
So if you need to unsubscribe from the event at a later time, you'd be best to actually create a delegate instance so you can hang onto the reference for later.
var myDelegate = delegate(sender, e){UpdateMyUI()};
myObservableCollection.CollectionChanged += myDelegate;
myObservableCollection.CollectionChanged -= myDelegate;
If you need to unsubscribe from an event, you need an instanced reference. Unfortunately, that means you can't use that particular syntax.
It's an ok way to go, unless myObservableCollection is going to live longer than 'this', in which case you could end up with a memory leak, as the delegate which is created behind the scenes will conserve a reference to your 'this', which will keep it alive. If you are repeatedly creating and 'destroying' whatever is listening to the event, you will find that they aren't being collected by the garbage collector.
If this is a problem, you can go the route suggested in the answers, conserving a reference to the handler, which you must create first.
Another solution is to use weak references to create an event handler which will allow the subscriber to be collected if there are not other references. I've explored this solution in this question and answer.