How to create a Weak Referenced Event Handler? - c#

I am doing research on how to properly create a weak referenced event handler. Since WPF has already a solution for avoiding memory leaks with events, I decompiled the "WeakEventManager" class and spent some time on analysing it.
As I found out, the "WeakEventManager" class relies on creating and storing a weak reference to the target object as well as to the event handler delegate. Here are some code segments:
this._list.Add(new WeakEventManager.Listener(target, handler));
public Listener(object target, Delegate handler)
{
this._target = new WeakReference(target);
this._handler = new WeakReference((object) handler);
}
I am asking myself if this simple solution would already be working or did I overlook an important aspect, since most other solutions I found on the Internet are complex and hard to understand. The best solution I could find so far
uses an unbound delegate. That is some kind of wrapper delegate that takes the event handler and event subscriber instance as a parameter (yes, it requires the event subscriber object to be passed in during delegate invocation).
You can find this great article here:
http://diditwith.net/CommentView,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx#commentstart
The "WeakEventManager" class doesnt't rely on knowing the subscriber class or any additional information. Beyond that it also works with anonymous delegates. Why do developers spent so much time on writing a solution that is not only working but also convenient to use, if a solution only requires them to store a weak reference to the delegate? What's the catch?
Update: Because someone downvoted this question (may be it is a little bit unspecific), I want to give a more precise question:
Is that source code above all it takes to create a working weak event handler? If not, what is missing?

did I overlook an important aspect
Yes, an important one. You traded one "leak" for another. Instead of preventing the event subscriber objects from getting garbage collected, you now prevent WeakReference objects from getting collected. You are not ahead.
What is also required is a mechanism to get those stale WeakReferences cleaned-up. You don't need them anymore when their IsAlive property returns false, you then remove it from _list. But you have to check that separately, some code needs to take care of that. An obvious choice is to check when an event is added or when it is fired. But that isn't enough, since client code only ever adds at initialization and you can't get a guarantee that the event is consistently fired.
So some kind of scheme is required to do it later. Anything is possible and nothing is quite ideal because it is a lot of busy-work with often not getting anything done. Making the right choice is important. And that certainly includes not doing this at all, it tends to be a band-aid over a design problem.

The idea behind the WeakEventManager is that it keeps a list of weak references to the target object of the events and a list of handlers it must call, but does not "tie them together" (as directly subscribing to events typically does), allowing the target to be garbage collected (and periodically checked so that the "subscribed" delegate list is emptied accordingly when the source is garbage collected).
This, which sounds easy, requires a lot of plumbing code, and that's all the WeakEventManager does (do the plumbing for you in an easy to use manner).
If you are cloning out WeakEventManager to your own implementation (or using the built-in) and it does that, then yes, that's all you need to do. If that's not what you are asking, then the question is unclear to me.

Is that source code above all it takes to create a working weak event handler? If not, what is missing?
That is the most important bit, the rest of the Listener class is important as well, not to mention the manual plumbing required to support this non-delegate event handler.
For instance check out ListenerList.DeliverEvent which is a bit more involved than the usual Invoke call.
Basically the normal event system assumes strong references so in order to use WeakReference you end up having to add a lot of the translation logic yourself as well as deciding how to handle events that never fire due to using WeakReference.

Related

Optimizing use of C# events?

I have a game in which players connect and see a list of challenges. In the code, challenges are stored in a dictionary by their status so I have a Dictionary<string, List<Challenge>> to store them.
I have a class that handles all related challenges actions, such as retrieving them from a server, and this class sends events to notify interested objects about the update. My problem is my delegate for the event is sending the whole dictionary and I'm realizing this is probably very bad in terms of garbage created or even execution speed.
My app will run on mobile and I'm working on Unity so I'm limited to .Net 3.5 (some 4 features). Performance is critical here so I would like to know what would be a more efficient way of doing this ?
The only thing I see right away would be to remove the dictionary from the event delegate and just access my singleton's instance variable instead of having it as a parameter. But I want to be sure there is no better way and that this will indeed be more efficient.
Classes are reference types and Dictionary<TKey, TValue> is a class, therefore, you're not copying the dictionary but just pointing to the same one from different references (for example, the event args providing a reference to the so-called dictionary).
If you're very worried about memory issues with event handlers, you can take a look at weak event pattern, which can led to prevent some memory leaks in some use cases (but you'll need .NET 4.0 at least...).

When to use Weak Events?

I was refering MSDN tutorial on weak events. I understood the basics. I am working on a non-WPF project and my class is exposing certain events. My question is that does the weak events
completely replace old event pattern? Is it good to use it every classes that is exposing events? What are the side effects of using weak events liberally?
Based on the reading I have done, there does not appear to be any specific negatives to using WeakEvents, except for the fact that it is more verbose to do so. Additionally, you should be able, in most cases, to manually unregister from events when you no longer need them. In some cases, this won't be possible. For example, the MSDN page you reference mentions when you should use WeakEvents:
http://msdn.microsoft.com/en-us/library/aa970850.aspx
Certain scenarios inherently lend themselves to the application of the weak event pattern. One such scenario is data binding. In data binding, it is common for the source object to be completely independent of the listener object, which is a target of a binding. Many aspects of WPF data binding already have the weak event pattern applied in how the events are implemented.
The only person who has presented any type of negative to them is this blog:
http://blog.catenalogic.com/post/2011/11/23/A-weak-event-listener-for-WPF-Silverlight-and-Windows-Phone-7.aspx
There are a few downsides about using a weak event listeners in general:
It’s notation is ugly, the “original” .NET way looks way better
You have to name the event by string, that sucks (if you know a better way, contact me!)
It can only handle events with a handler of EventHandler
You become a lazy developer not caring about subscriptions
Essentially, they should be used for events that your objects will subscribe to for the entire length of their existence, and only disconnect from when the objects are disposed. For everything else, using the traditional events and registering/unregistering the events manually is preferred.
There are two issues that must be considered with weak events:
Weak events allow subscribers to subscribe to events (messages) even without knowing the identity of the class raising the event. In some cases that may be desired even necessary. However, in some cases that can introduce unnecessary complexity and a level of indirection that makes the code harder to manage or control at run time.
The major downside of using weak events is that it may encourage developers to neglect the part where they unsubscribe from events (messages). In that case event handlers may be invoked even after the subscribers "go out of scope". Consider a subscriber that does not explicitly unsubscribe and that becomes garbage collectable but was not yet garbage collected. The weak event manager will not be able to detect that state and because of that it will still call the event handler of that subscriber. This can lead to all kind of unexpected side effects.
See more details at The Weak Event Pattern is Dangerous.
See this source code that illustrates this issue using the MvvMCross messaging plugin as a weak event manager.
When to use weak events?
From MSDN
Listening for events can lead to memory leaks
So you should use weak events with the purpose of avoiding those leaks
Is it good to use it every classes that is exposing events? What are the side effects of using weak events liberally?
See Why is the implementation of events in C# not using a weak event pattern by default?. Leaking from "strong" events is not that usual, weak events come with a performance cost and have a semantic difference that may not be desired in every context, misuse of a weak reference can cause the event to intermittently not to fire (in contrast to misusing a normal event causing a memory leak)
Example memory leak that could be avoided
Static classes and Singletons are villains when talking about memory leaks, when they acquire a reference to some other object they will prevent the object from being garbage collected, and thus, leak the object forthe lifespan of the application, here is an example where I met with the need for a weak reference to avoid a memory leak
First of all, weak events are not always necessary, like others have been saying only when the source object outlive the subscriber. If that is the case, then yes, you should use it, this is what people call The Weak Event Pattern.
The side effects are just that you will have to write more code. Microsoft provides the WeakEventManager class and in WPF exist some specific implementations, but you can create your own inheriting from the base WeakEventManager.
The way it works is by using weak references from the source object to the listener so this relationship doesn’t stop the GC from collecting these objects. For some specific applications this can solve a lot of performance issues.

Static Deconstructor

I have class instantiated in a web service that, in a static member, holds on to some resources. If I was not statically holding on to these resources, I'd probably access them through some IDisposable object where I could release the resources on Dispose. Regardless of whether or not holding on to this session is a good idea, does .NET provide any way to call any clean up code when a type is statically deconstructed?
PLEASE DO NOT ANSWER THIS QUESTION WITH ANYTHING LIKE "STOP HOLDING RESOURCES IN A STATIC MEMBER VARIABLE". I understand the drawbacks to holding on to this information statically and am willing to accept the consequences (we're using it to cut processing time from 58 hours to 4 hours for some batch processing that we do). The question specifically is: given this situation, is there anyway for me to nicely clean up those resources?
EDIT:
I understand that the class will live for the rest of the process, but with static constructors .NET gives you the opportunity to do something when that type is loaded into memory. Can you do anything on the opposite end?
There actually is no way to do it from managed code. What you want is to handle your assembly being unloaded, but that doesn't happen under most circumstances when you want it to.
In more detail:
There is an AppDomain.DomainUnload event ( http://msdn.microsoft.com/en-us/library/system.appdomain.domainunload.aspx ) you can handle. This handles when your application domain gets unloaded from its hosting process (say ASP.NET).
However, if you are an EXE, or the hosting EXE is being recycled, this will not be raised. If you set up correctly, you might be able to handle the native DLL_PROCESS_DETACH and bounce that back to managed code, but because of the loader lock you will have to be very careful what you do from that context (anything that triggers an assembly load will deadlock).
You can read this for some insight on what cleanup is requited (hint: not much): http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
Basically, the only thing you need to worry about is flushing buffers to disk, and if you need to do anything more complex, you have already screwed up. malloc(), and therefore new() could crash your program instantly. This applies to managed code as well.
The question does not really make sense, static lives for the lifetime of the process, when a process ends then everything is cleaned up by the OS. A process cannot continue to use resources if it is not running any longer.
When is the last point this static state is going to be important? At this moment, you should destruct it.
Destruct might mean something like "release some unmanaged memory, write out a cache to the database and set the static variable to null".
The last point of access will mean different things in different applications. In an ASP.NET application, you cannot reliably determine this point. It comes when the Application_End event or the AppDomain.Unload events fire, whichever comes first. The same in WCF. In a WinForms app you would to it after the main form has closed or as the last line of the main application.
In any case you need to do the cleanup yourself.
Alternative: You can encapsulate your state into a finalizable object. It will be cleaned up on AppDomain unload. If you write a so called critical finalizer you are pretty much guaranteed that your cleanup will execute.
You cannot destruct something that hasn't been instantiated.
I think you should use Singleton pattern instead of holding all data statically.
If the objects you are storing as static members properly implement IDisposable, then the .net runtime should take care of any resources when the app unloads. If any of the objects do not do this, then I suggest you create wrapper classes that implement IDisposable so that you can clean up after yourself.
IDisposable on MSDN

pattern to release objects in a managed language

In a complex application (involving inversion of control and quite some classes) it is hardly possible to know when a certain object won't be referenced anylonger.
First Question: Suggests the statement above that there is a design flaw in such an application, since there is a pattern saying: "In all OO programming it is about objects using other types of objects to ease up implementation. However: For any object created there should be some owner that will take care of its lifetime."
I assume it is save to state that traditional unmanaged OO programming works like stated above: Some owner will eventually free / release the used object.
However the benefit of a managed language is that in principle you don't have to care about lifetime management anymore. As long an object is referenced anyhow (event-handler...) and from anywhere (maybe not the "owner") it lives and should live, since it is still in use.
I really like that idea and that you don't have to think in terms of owner relationships. However at some point in a program it might get obvious that you want to get rid of an object (or at least mute it in a way as it wouldn't be there).
IStoppable: a suggestion of a design pattern
There could be an interface like "IStoppable", with a "Stop()" method and an "Stopped" event, so that any other object using it can remove their references onto the object. (Therefore would need to unplug their OnStopped event handler within the event handler if that is possible). As a result the object is no longer needed and will get collected.
Maybe it is naive but what i like to believe about that idea is that there wouldn't be an undefined state of the object. Even if some other object missed to unregister itself on OnStopped it will just stay alive and can still get called. Nothing got broken just by removing most references onto it.
I think this pattern can be viewed as an anarchistic app design, since
it is based on the idea that ANY other object can manage the lifetime of an IStoppable
there is no need for an owner
it would be considered as OK to leave the decision of unregistering from an IStoppable to those using it
you don't need to dispose, destroy or throw away - you just stop and let live (let GC do the dirty part)
IDisposable: from scatch and just to check a related pattern:
The disposable pattern suggests that you should still think and work like in unmanaged OO programming: Dispose an object that you don't need anylonger.
using is your friend in a method (very comfortable!)
an own IDisposable implementation is your friend otherwise.
after using it / calling Dispose you shouldn't call it anylonger: undefined behaviour.
implementation and resource centric: it is not so much about when and why, but more about the details of reclaiming resources
So again: In an application where i don't have in mind if anything else but an "owner" is pointing to an object, it is hard to ensure that noone will reference and call it anylonger.
I read of a "Dispose" event in the Component class of .NET. Is there a design pattern around it?
Why would i want to think in terms of Disposables? Why should i?
In a managed world...
Thanks!
Sebastian
I personally don't like the idea of IStoppable, as defined above. You're saying you want any object to manage the lifetime of the object - however, a defined lifecycle really suggests ownership - allowing multiple objects to manage the lifetime of a single object is going to cause issues in the long
IDisposable is, however, a well defined pattern in the .NET world. I wrote an entire series on implementing IDisposable which is a decent introduction to it's usage. However, it's purpose is for handling resource which have an unmanaged component - when you have a managed object that refers to a native resource, it's often desirable to have explicit control of the lifetime of that resource. IDisposable is a defined pattern for handling that situation.
That being said, a proper implementation of IDisposable will still clean up your resources if you fail to call Dispose(). The downside is that the resource will be cleaned up during the object's finalization, which could occur at any arbitrary point after the object is no longer used. This can be very bad for quite a few reasons - especially if you're using native resources that are limited in nature. By not disposing of the resource immediately, you can run out of resources before the GC runs on the object, especially if there isn't a lot of memory pressure in the system.
Ok first I would point out a few things I find uncomfortable about your IStoppable suggestion.
IStoppable raises event Stopped, consumers must know about this and release references. This is a bit complex at best, problematic at worst. Consumers must know where every reference is in order to remove/reset the reference.
You claim "... Nothing got broken just by removing most references onto it.". That entirely depends on the object implementing IStoppable and it's uses. Say, for example, my IStoppable object is an object cache. Now I forget about or ignore the event and suddenly I'm using a different object cache as the rest of the world... maybe that is ok, maybe not.
Events are a horrible way to provide behavior like this due to the fact that exceptions prove difficult to handle. What does it mean when the third out 10 event handlers throws an exception in the IStoppable.Stopped event?
I think what your trying to express is an object that may be 'owned' by many things and can be forcefully released by one? In this case you might consider using a reference counter pattern, more like old-school COM. That of course has issues as well, but they are less of a problem in a managed world.
The issue with a reference counter around an object is that you come back to the idea of an invalid/uninitialized object. One possible way to solve this is to provide the reference counter with a valid 'default' instance (or a factory delegate) to use when all references have been release and someone still wants an instance.
I think you have a misunderstanding of modern OO languages; in particular scope and garbage collection.
The lifetime of the objects are very much controlled by their scope. Whether the scope is limited to a using clause, a method, or even the appdomain.
Although you don't necessarily "care" about the lifetime of the object, the compiler does and will set it aside for garbage collection as soon as it goes out of scope.
You can speed up that process by purposely telling the garbage collector to run now, but that's usually a pointless exercise as the compiler will optimize the code to do so at the most opportune time anyway.
If you are talking about objects in multi-threaded applications, these already expose mechanisms to stop their execution or otherwise kill them on demand.
Which leaves us with unmanaged resources. For those, the wrapper should implement IDisposable. I'll skip talking about it as Reed Copsey has already covered that ground nicely.
While there are times a Disposed event (like the one used by Windows Forms) can be useful, events do add a fair bit of overhead. In cases where an object will keep all the IDisposables it ever owns until it's disposed (a common situation) it may be better to keep a List(Of IDisposable) and have a private function "T RegDisp<T>(T obj) where T:IDisposable" which will add an object to the disposables list and return it. Instead of setting a field to SomeDisposable, set it to RegDisp(SomeDisposable). Note that in VB, provided all constructor calls are wrapped in factory methods, it's possible to safely use RegDisp() within field initializers, but that cannot be done in C#.
Incidentally, if an IDisposable's constructor accepts an IDisposable as a parameter, it may often be helpful to have it accept a Boolean indicating whether or not ownership of that object will be transferred. If a possibly-owned IDisposable will be exposed in a mutable property (e.g. PictureBox.Image) the property itself should be read-only, with a setter method that accepts an ownership flag. Calling the set method when the object owns the old object should Dispose the old object before setting the new one. Using that approach will eliminate much of the need for a Disposed event.

When should weak references be used?

I recently came across a piece of Java code with WeakReferences - I had never seen them deployed although I'd come across them when they were introduced. Is this something that should be routinely used or only when one runs into memory problems? If the latter, can they be easily retrofitted or does the code need serious refactoring? Can the average Java (or C#) programmer generally ignore them?
EDIT Can any damage be done by over-enthusiastic use of WRs?
Weak references are all about garbage collection. A standard object will not "disappear" until all references to it are severed, this means all the references your various objects have to it have to be removed before garbage collection will consider it garbage.
With a weak reference just because your object is referenced by other objects doesn't necessarily mean it's not garbage. It can still get picked up by GC and get removed from memory.
An example: If I have a bunch of Foo objects in my application I might want to use a Set to keep a central record of all the Foo's I have around. But, when other parts of my application remove a Foo object by deleting all references to it, I don't want the remaining reference my Set holds to that object to keep it from being garbage collected! Really I just want it to disappear from my set. This is where you'd use something like a Weak Set (Java has a WeakHashMap) instead, which uses weak references to its members instead of "strong" references.
If your objects aren't being garbage collected when you want them to then you've made an error in your book keeping, something's still holding a reference that you forgot to remove. Using weak references can ease the pain of such book keeping, since you don't have to worry about them keeping an object "alive" and un-garbage-collected, but you don't have to use them.
You use them whenever you want to have a reference to an object without keeping the object alive yourself. This is true for many caching-like features, but also play an important role in event handling, where a subscriber shall not be kept alive by being subscribed to an event.
A small example: A timer event which refreshes some data. Any number of objects can subscribe on the timer in order to get notified, but the bare fact that they subscribed on the timer should not keep them alive. So the timer should have weak references to the objects.
Can any damage be done by
over-enthusiastic use of WRs?
Yes it can.
One concern is that weak references make your code more complicated and potentially error prone. Any code that uses a weak reference needs to deal with the possibility that the reference has been broken each time it uses it. If you over-use weak references you end up writing lots of extra code. (You can mitigate this by hiding each weak reference behind a method that takes care of the checking, and re-creates the discarded object on demand. But this may not necessarily be as simple as that; e.g. if the re-creation process involves network access, you need to cope with the possibility of re-creation failure.)
A second concern is that there are runtime overheads with using weak references. The obvious costs are those of creating weak references and calling get on them. A less obvious cost is that significant extra work needs to be done each time the GC runs.
A final concern is that if you use a weak references for something that your application is highly likely to need in the future, you may incur the cost of repeatedly recreating it. If this cost is high (in terms of CPU time, IO bandwidth, network traffic, whatever) your application may perform badly as a result. You may be better off giving the JVM more memory and not using weak references at all.
Off course, this does not mean you should avoid using weak references entirely. Just that you need to think carefully. And probably you should first run a memory profiler on your application to figure out where your memory usage problems stem from.
A good question to ask when considering use of a WeakReference is how one would feel if the weak reference were invalidated the instant no strong references existed to the object. If that would make the WeakReference less useful, then a WeakReference is probably not the best thing to use. If that would be an improvement over the non-deterministic invalidation that comes from garbage-collection, then a WeakReference is probably the right choice.

Categories