Unsubscribe to child object prop changed events - c#

Say I have a object Client that has a child StatusType object. Both implement INotifyPropertyChanged.
The Client subscribes to the prop changed event in the property after checking for null and making sure value is different
public StatusType Status
{
get { return _status ?? (_status = this.GetNewStatusType()); }
set
{
if (!(_status ?? (_status = this.GetNewStatusType())).Equals(value))
{
_status.PropertyChanged -= Status_PropertyChanged;
_status = value;
_status.PropertyChanged += Status_PropertyChanged;
base.OnPropertyChanged("Status");
}
}
}
Client listens for property changed events and bubbles it up.
void Status_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnPropertyChanged("Status." + e.PropertyName);
}
Both Client and StatusType inherit from EntitiesBase, which does the actual heavy lifting of implementing INotifyPropertyChanged.
So my actual question is do I need have Client unsubscribe from StatusType.PropertyChanged event for memory reasons? If so, should I use a deconstructor, or have client implement IDisposable?
If I was to use a deconstructor, would it look something like this?
~Client()
{
if (_status != null)
{
_status.PropertyChanged -= Status_PropertyChanged;
_status = null;
}
}
Thanks in advance. There are times in our application where we might have over 1000 clients in memory and I want to make sure I am being efficient.

You could be creating a memory leak if these clients remain in memory indefinitely and their AppDomain is never unloaded. IDisposable might be a better route as you will have a deterministic approach to cleaning up the handlers you no longer need.
[Edit] Keep in mind that even though you may remove the delegate from the event's invocation list you will not free up the memory until the GC runs.
Also this might be of interest to you: http://msdn.microsoft.com/en-us/library/aa970850.aspx

Related

Can subscribing to events with anonymous lamba in static method cause memory leak?

My understanding is that it is always the subscriber (consumer) of an event that is in risk of being leaked (if the producer lives longer). If I subscribe to an (non-static) event with an anonymous lambda function inside a static method, I should not have to unsubscribe if I want the lambda to live as long as the producer lives?
There is a variant of the question (Does lambda event subscription create memory leak?) with this answer, quoting:
Additionally, that lambda expression isn't using any variables from this, so it would probably be implemented by a static method with no target anyway... I assume the real situation you're concerned with has a more interesting lambda body.
I interpret this to mean that you might have to unsubscribe if the lambda expression is using variables from the target (this), but in a static method, this does not exist, hence the question.
The specific code i'm thinking of comes from this answer (see below). The comments to that answer suggests that you have to unsubscribe to avoid memory leaks, but is this really true? What is being leaked exaktly? Another answer to the same question that tried to handle unsubscription, actually added a potential memory leak instead (by storing the eventhandlers in a static dictionary that might not be cleaned up).
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
// There should be no need to unsubscribe to e.OldValue?
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
// This event handler will not keep the columns alive, and the lambda will only be alive as long as the columns is alive?
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
// Clear dataGrid.Columns
...
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
// Add to dataGrid.Columns
...
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
...
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
...
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
...
}
};
}
Considering the answer you referenced and the comment about the leak, you have to note the following.
There is an object of type ObservableCollection<DataGridColumn> in a viewmodel. In WPF, viewmodels might live longer than their views (e.g. you can switch different views for the same viewmodel or you can keep your viewmodel alive the whole time and only display the corresponding view when needed, think of a hideable tool window, for example).
That viewmodel object gets an event subscription with a lambda:
columns.CollectionChanged += (sender, e2) => { /* ... */ };
The lambda itself captures a view element - the dataGrid:
// lambda body
{
// ...
dataGrid.Columns.Clear();
}
Now, you have a strong reference chain: columns -> lambda object -> dataGrid.
That means - the dataGrid object will live as long as the columns object is alive. As noted above, this is a viewmodel object and it can live the whole time the app is running. Thus, the dataGrid will continue to live even if the corresponding view is not visible anymore and has no other references.
That is the leak they talk about.

How do I fix a memory leak caused by an object referenced by a ContextMenuStrip

I have used dotMemory to locate a memory leak. The object I want gone is referenced by an event handler through a ToolStripMenuItem and ContextMenuStrip. The object contains these properties:
public override ContextMenuStrip PopupMenu
{
get
{
ContextMenuStrip myPopup = new ContextMenuStrip();
myPopup.Items.Add(ItemDelete);
return myPopup;
}
}
public ToolStripMenuItem ItemDelete
{
get
{
ToolStripMenuItem itemDelete = new ToolStripMenuItem("Delete " + name);
itemDelete.Enabled = Deletable;
itemDelete.Image = Properties.Resources.del;
itemDelete.Click += ItemDelete_Click;
return itemDelete;
}
}
I have simplified the code, the popup menu has about a dozen menu items, which all seem to be holding on to this object after I use the popup menu to delete the object. I have tried overriding the base delete method for the object to remove the handlers, but that did not work.
public override void delete()
{
if (PopupMenu != null)
{
ItemDelete.Click -= ItemDelete_Click;
}
base.delete();
}
Without a good, minimal, complete code example, it's impossible to know for certain what the problem is, never mind the best fix. That said…
Based on the tiny amount of code you've posted so far, it appears that you've misused the property feature in C#, and in doing so have obfuscated the code enough that you have been unable to recognize the bug. In particular, your ItemDelete property is creating a new object every time you call it, which is a horrible way to implement a getter of this kind. For the code to work correctly, you'd have to be careful to only ever call that property getter once, and manually cache the result somewhere else.
Creating a new object in a property getter isn't inherently bad, but it should be done only if that object will be cached by the property getter itself and reused for subsequent calls, or if that object is semantically a simple value (preferably an actual value type, but a simple, ummutable reference type would be fine too), where a newly created object is functionally identical to any previously created object (i.e. they can be used interchangeably without affecting the correctness of the code).
Given the above, it is possible that you would find the following alternative a useful way to fix the problem:
private Lazy<ToolStripMenuItem> _itemDelete =
new Lazy<ToolStripMenuItem>(() => _CreateItemDelete());
private ToolStripMenuItem _CreateItemDelete()
{
ToolStripMenuItem itemDelete = new ToolStripMenuItem("Delete " + name);
itemDelete.Enabled = Deletable;
itemDelete.Image = Properties.Resources.del;
itemDelete.Click += ItemDelete_Click;
return itemDelete;
}
public ToolStripMenuItem ItemDelete
{
get
{
return _itemDelete.Value;
}
}
This will defer creation of the ToolStripMenuItem object until the first time that the property getter is called, but will on subsequent calls to the getter return that object created on the first call.
In this way, you will ensure that when you execute the statement ItemDelete.Click -= ItemDelete_Click; later, you are actually removing the event handler from the original object, rather than some new object you created at that time.

C# - Static events on non-static classes

There are situations where I'm quite fond of static events, but the fact that I rarely see them in other people's code makes me wonder if I'm missing something important. I found a lot of discussions about static events on this site, but most of them deal with situations that I'm not interested in (like on static classes) or where I wouldn't think of using them in the first place.
What I am interested in are situations where I might have many instances of something and a single instance of a long-living "manager" object that reacts to something on those instances. A very simple example to illustrate what I mean:
public class God {
//the list of followers is really big and changes all the time,
//it seems like a waste of time to
//register/unregister events for each and every one...
readonly List<Believer> Believers = new List<Believer>();
God() {
//...so instead let's have a static event and listen to that
Believer.Prayed += this.Believer_Prayed;
}
void Believer_Prayed(Believer believer, string prayer) {
//whatever
}
}
public class Believer {
public static event Action<Believer, string> Prayed;
void Pray() {
if (Prayed != null) {
Prayed(this, "can i have stuff, please");
}
}
}
To me, this looks like a much cleaner and simpler solution than having an instance event and I don't have to monitor changes in the believers collection either. In cases where the Believer class can "see" the God-type class, I might sometimes use a NotifyGodOfPrayer()-method instead (which was the preferred answer in a few similar questions), but often the Believer-type class is in a "Models"-assembly where I can't or don't want to access the God class directly.
Are there any actual downsides to this approach?
Edit: Thanks to everyone who has already taken the time to answer.
My example may be bad, so I would like to clarify my question:
If I use this kind of static events in situations, where
I'm sure there will only ever be one instance of the subscriber-object
that is guaranteed to exist as long as the application is running
and the number of instances I'm watching is huge
then are there potential problems with this approach that I'm not aware of?
Unless the answer to that question is "yes", I'm not really looking for alternative implementations, though I really appreciate everyone trying to be helpful.
I'm not looking for the most pretty solution (I'd have to give that prize to my own version simply for being short and easy to read and maintain :)
One important thing to know about events is that they cause objects which are hooked to an event not to be garbage collected until event owner is garbage collected, or until event handler is unhooked.
To put it into your example, if you had a polytheistic pantheon with many gods, where you promoted and demoted gods such as
new God("Svarog");
new God("Svantevit");
new God("Perun");
gods would remain in your RAM while they are attached to Believer.Prayed. This would cause your application to leak gods.
I'll comment on design decision also, but I understand that example you made is maybe not best copy of your real scenario.
It seems more reasonable to me not to create dependency from God to Believer, and to use events. Good approach would be to create an event aggregator which would stand between believers and gods. For example:
public interface IPrayerAggregator
{
void Pray(Believer believer, string prayer);
void RegisterGod(God god);
}
// god does
prayerAggregator.RegisterGod(this);
// believer does
prayerAggregator.Pray(this, "For the victory!");
Upon Pray method being called, event aggregator calls appropriate method of God class in turn. To manage references and avoid memory leaks, you could create UnregisterGod method or hold gods in collection of weak references such as
public class Priest : IPrayerAggregator
{
private List<WeakReference> _gods;
public void Pray(Believer believer, string prayer)
{
foreach (WeakReference godRef in _gods) {
God god = godRef.Target as God;
if (god != null)
god.SomeonePrayed(believer, prayer);
else
_gods.Remove(godRef);
}
}
public void RegisterGod(God god)
{
_gods.Add(new WeakReference(god, false));
}
}
Quick tip: Temporarily store event delegate as listeners might unhook their event handlers
void Pray() {
var handler = Prayed;
if (handler != null) {
handler(this, "can i have stuff, please");
}
}
Edit
Having in mind details you added about your scenario (huge number of event invokers, constant and single event watcher) I think you chose right scenario, purely for efficiency reasons. It creates least memory and cpu overhead. I wouldn't take this approach generally, but for scenario you described static event is very pragmatic solution that I might take.
One downside I see is flow of control. If your event listener is created in single instance as you say, then I would leverage singleton (anti)pattern and invoke method of God from Believer directly.
God.Instance.Pray(this, "For the victory!");
//or
godInstance.Pray(this, "For the victory!");
Why? Because then you get more granular control over performing action of praying. If you decide down the line that you need to subclass Believer to a special kind that doesn't pray on certain days, then you would have control over this.
I actually think that having an instance even would be cleaner and defiantly more readable.
It is much more simple to view it as, an instance is preying, so his pray event gets trigger. And I don't see ant downsides for that. I don't think that monitor changes is not more of a hustle than monitoring the static event. but is the correct way to go...
Monitoring the list:
Change the list to be an ObservableCollection (and take a look at NotifyCollectionChangedEventArgs ).
Monitor it by:
public class God {
readonly ObservableCollection<Believer> Believers = new ObservableCollection<Believer>();
public God() {
Believers = new ObservableCollection<T>();
Believers.CollectionChanged += BelieversListChanged;
}
private void BelieversListChanged(object sender, NotifyCollectionChangedEventArgs args) {
if ((e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) && e.OldItems != null)
{
foreach (var oldItem in e.OldItems)
{
var bel= (Believer)e.oldItem;
bel.Prayed -= Believer_Prayed;
}
}
if((e.Action==NotifyCollectionChangedAction.Add || e.Action==NotifyCollectionChangedAction.Replace) && e.NewItems!=null)
{
foreach(var newItem in e.NewItems)
{
foreach (var oldItem in e.OldItems)
{
var bel= (Believer)e.newItem;
bel.Prayed += Believer_Prayed;
}
}
}
}
void Believer_Prayed(Believer believer, string prayer) {
//whatever
}
}

Implementation of BeginUpdate and EndUpdate

1) I'm working on a project and I saw this piece of code, I don't understand what is the point of the Monitor.Lock statement. Can someone explain what its trying to do?
2) the postscript underscroll in the parameter name is really annoying, anyone else seen this naming convention?
public class FieldsChangeableHelper<T> : IFieldsChangeable<T>
{
object _lock;
int _lockCount;
FieldChanges<T> _changes;
public FieldsChangeableHelper()
{
_lock = new object();
_lockCount = 0;
}
public void AddChange(T field_, object oldValue_)
{
if (_changes == null)
_changes = new FieldChanges<T>(field_, oldValue_);
else
_changes.AddChange(field_, oldValue_);
if (RaiseEvent(_changes))
_changes = null;
}
#region IFieldsChangeable Members
public void BeginUpdate()
{
if (System.Threading.Interlocked.Increment(ref _lockCount) == 1)
Monitor.Enter(_lock);
}
public void EndUpdate()
{
if (System.Threading.Interlocked.Decrement(ref _lockCount) == 0)
{
FieldChanges<T> changes = _changes;
_changes = null;
Monitor.Exit(_lock);
RaiseEvent(changes);
}
}
protected bool RaiseEvent(FieldChanges<T> changes_)
{
if (_lockCount == 0 && Changed != null && changes_ != null)
{
Changed(this, changes_);
return true;
}
return false;
}
public event FieldsChanged<T> Changed;
#endregion
}
Monitor.Lock locks the portion of code when multiple thread tries to execute the same piece in parallel. It is made to ensure that only 1 guy is altering/executing the context. Look at the MSDN.
Although its best practice that the locking object is always static, but in your case it is not. Which might pose some problem if your instantiating multiple objects on an open type.
Note one thing, in generics static on open T is different for different type, i.e static member in an Open Type class in your case is different for T i.e DateTime, string, etc.
In csharp, private members of a type are usually named with prefixed _
The way i read it: BeginUpdate() ensures that the current thread calling has exclusive access to the instance and that change events practically will be batched and raised once EndUpdate is called. The author wanted to deal with recursion by itself (e.g. calling BeginUpdate() on the same thread multiple times) and a mechanism to batch UpdateEvents untill after the lock has been released. Because, there is a potential deadlock when raising Events when you still have a lock on yourself. event subscribers might want to access your members and therefore have to lock the sender instance which is already locked.
The whole conditional locking is not required (if my analyses is correct ofcourse) since locks based on the Monitor class are recursive and counted.
There is another problem with the locking mechanism, that is: currently when one thread holds a lock. The second thread wont even wait for the lock but will simply continue without a lock since the lock is conditional! this seems like a big bug!
Regarding the naming convention. I use it myself for a way of differentiating privates from parameters and locals. Its a preference which many C# coding conventions recommend. This helps in a case like this:
void Method(int number)
{
// no need to refer to this since:
//this.number = number;
// can be replaced with
_number = number;
}

Raising an event thread safely

I'm sure I've seen this around before but I'm wondering how I should raise an event thread-safely.
I have a message despatch thread which looks somthing like.
while(_messages > 0){
Message msg;
// get next message
if (MessageDispatched != null)
MessageDispatched(this, new MessageDispatchedEventArgs(msg.Msg, msg.Params));
}
I can see that it may be posible for MessageDispatched to be come null after the check. from a MS blog I've seen:
var handler = MessageDispatched;
if (handler != null)
handler(this, new MessageDispatchedEventArgs(msg.Msg, msg.Params));
Which does stop the possibility of the reference becoming null after the check occurring. I'm wondering how to handle the case where the delegate is disposed (or even if it can?)
Should I just need to stick a try / catch around it, as its probably very rarely going to occur?
Edit
After reading answers I've considered making my class to handle this - quickly it looks something whats below, but I'm running into a few issues which make it not as clean as I want - maybe someone has an idea how to do that?
public class ThreadSafeEvent<TDelegate>
// where TDelegate : Delegate why is this a non allowed special case???
{
List<TDelegate> _delegates = new List<TDelegate>();
public void Subscribe(TDelegate #delegate)
{
lock (_delegates)
{
if (!_delegates.Contains(#delegate))
_delegates.Add(#delegate);
}
}
public void Unsubscibe(TDelegate #delegate)
{
lock (_delegates)
{
_delegates.Remove(#delegate);
}
}
// How to get signature from delegate?
public void Raise(params object[] _params)
{
lock (_delegates)
{
foreach (TDelegate wrappedDel in _delegates)
{
var del = wrappedDel as Delegate;
del.Method.Invoke (del.Target, _params);
}
}
}
}
The latter structure will make sure you won't get a null reference exception calling the handler on non-Itanium architectures.
However, it leads to another possible issue -- it's possible for a client that registered an event handler to have the handler called after it's been removed. The only way to prevent that is to serialize raising the event and registering the handler. However, if you do that, you have a potential deadlock situation.
In short, there are three potential classes of ways this can break -- I go with the way you've done it here (and MS recommends) and accept that it is possible for an event handler to get called after it is unregistered.
Please, check this out: Checking for null before event dispatching… thread safe?
Read this post from Eric Lippert : Events and Races

Categories

Resources