When I finalized my article about memory leaks, I removed a part about Infragistics NetAdvantage. Here it is. It may be useful to some of you. Warning: It's based on NetAdvantage 7.3, and may or may not apply to recent versions.
Let's take an example. In project X, visual controls from the Infragistics NetAdvantage suite are used to build the GUI. One of these controls is the UltraToolbar. As told by its name, this control is used to display toolbars. The way a UltraToolbar is used is via a UltraToolbarsManager component. This works fine, except that even though the UltraToolbar class implements IDisposable, the UltraToolbarsManager class never calls the Dispose method on the UltraToolbars it manages. This is a bug. Fortunately, a workaround is easy to find: just call Dispose by yourself on each UltraToolbar. Unfortunately, this is not enough because UltraToolbar itself is buggy: it does not dispose the controls (buttons, labels, etc.) it contains. Again, the solution is to dispose each control the toolbar contain, but that's not so easy this time because each sub-control is different. Infragistics has the same problem with another set of objects: the custom editors you can create for cells in grids are not disposed automatically either.
Anyway, these are just specific examples. My point is that any libraries and components you use may cause leaks in your applications.
Later in the article:
Let's take an interesting example that shows another particularity of Infragistics NetAdvantage. The scenario is simple: just dynamically add a button to a form. The only special thing about this button is that it will be an UltraButton from Infragistics NetAdvantage.
Here is how the button is added to the form (UltraButtonForm.cs):
_ultraButton = new UltraButton();
_ultraButton.Text = "UltraButton";
_ultraButton.Location = new Point(10, 100);
Controls.Add(_ultraButton);
Nothing fancy here. We just create a new instance of UltraButton and add it to the list of controls of the form so that it gets displayed. This works fine. Even when the form is closed/disposed, everything gets released.
Now, let's do one more little thing: remove the button before closing the form.
Controls.Remove(_ultraButton);
Guess what: now there is a problem! And potentially a big one.
The problem is that the UltraButton is not released from memory this time. And it's not alone, as I'll show soon.
As you can see, the button is kept alive by an event from the Infragistics.Win.Office2007ColorTable class named ColorSchemeChanged. This happens because this is a static event and UltraButton uses its Dispose method to unsubscribe from this event.
Without the call to Controls.Remove, everything was fine because all the controls contained in the Controls property of a Windows Forms Control are automatically disposed. When a control is removed from the Controls collection, it won't be disposed unless you do it explicitely yourself.
Here, the leak is due to a static event named ColorSchemeChanged, or one of its friends. The only way to ensure that such references get released is to make sure that Dispose is invoked on ALL the Infragistics controls. This is achieved via invoking Dispose on all the other controls.
If you use Infragistics NetAdvantage you may already have seen ColorSchemeChanged, Office2007ColorTable, and their friend, and maybe thought that there was a bug in them that caused leaks. As you have seen, this is not a bug per se, but it can be a source of memory leaks if you don't pay careful attention to ensure that all controls get disposed.
So, we've just seen again what I exposed above with static events. What I want to stress here is that it's easy to introduce a leak with just a line of code. Would you have thought about memory leaks when adding the call to Controls.Remove?
An UltraButton may not be a big object, but if you have several of them and if you do the same operation multiple times, you'll start to see a bigger leak. In addition, this doesn't happen only with UltraButton, but also with most of the other Infragistics controls, and potentially with other objects that subscribe to static events and depend on Dispose for unsubscribing. The only way to ensure that all objects get fully released is to make sure that Dispose is invoked on all controls.
Sample source code
The MVVM pattern (Model-View-ViewModel, also known as M-V-VM, the PresentationModel pattern, or the ViewModel pattern) appeared a long time ago now, but it took some time before it became more documented and well known. Over the last few months, MVVM boomed, especially with an explosion of dedicated frameworks. It's difficult to know what each framework proposes and which one to choose. Fortunately, Jeremy Alles has compiled pointers to all the MVVM frameworks available today. He even lists the main features of each framework.
Jeremy Alles proposes a nice tour of the core WPF classes. It comes with a class diagram and quick descriptions.
I'll keep a link to it here for reference. It's the kind of document I'll refer to several times.
Covered classes include DispatcherObject, FrameworkTemplate, DependencyObject, Visual, UIElement, FrameworkElement, Control, and much more.
My new article, which I've been preparing over the last few months, is now available. It's about memory and resources leaks in .NET.
You'll find it in English on MSDN and in French on DotNetGuru.org. It's also available in PDF in English and in French.
Here is the table of content:
- Introduction
- Leaks? Resources? What do you mean?
- How to detect leaks and find the leaking resources
- Common memory leak causes
- Common memory leaks causes demonstrated
- How to avoid leaks
- Tools
- Conclusion
- Resources
Despite what a lot of people believe, it's easy to introduce memory and resources leaks in .NET applications. The Garbage Collector, or GC for close friends, is not a magician who would completely relieve you from taking care of your memory and resources consumption.
I'll explain in this article why memory leaks exist in .NET and how to avoid them. Don't worry, I won't focus here on the inner workings of the garbage collector and other advanced characteristics of memory and resources management in .NET.
It's important to understand leaks and how to avoid them, especially since they are not the kind of things that is easy to detect automatically. Unit tests won't help here. And when your application crashes in production, you'll be in a rush looking for solutions. So, relax and take the time to learn more about this subject before it's too late.
Mon nouvel article, que j'ai préparé durant ces derniers mois, est maintenant disponible. Il parle des fuites de mémoire et de ressources en .NET.
Vous le trouverez en français sur DotNetGuru.org et en anglais sur MSDN. Il est également disponible en PDF en français et en anglais.
Voici la table des matières :
- Introduction
- Fuites ? Ressources ? Qu'entendez-vous par là ?
- Comment détecter des fuites et repérer les ressources qui fuient
- Les causes habituelles de fuites de mémoire
- Les causes habituelles de fuites en pratique
- Comment éviter les fuites
- Outils
- Conclusion
- Ressources
En dépit de ce que beaucoup de personnes pensent, il est facile d'introduire des fuites de mémoire et de ressources dans les applications .NET. Le Garbage Collector, également appelé ramasse-miettes ou GC pour les intimes, n'est pas un magicien qui vous affranchirait totalement de vous soucier de la consommation de ressources et de mémoire.J'expliquerai dans cet article pourquoi les fuites de mémoire existent en .NET et comment les éviter. Ne vous en faites pas, je ne vais pas me focaliser ici sur le fonctionnement interne du garbage collector et autres caractéristiques avancées de la gestion de la mémoire et de ressources en .NETIl est important de comprendre les fuites et comment les éviter, particulièrement car elles n'entrent pas dans la catégorie des choses facilement détectables de manière automatisée. Les test unitaires ne vous aideront pas ici. Et quand votre application se plantera en production, vous serez à la recherche de solutions dans l'urgence. Alors, détendez-vous et prenez le temps dès maintenant d'en apprendre plus sur ce sujet avant qu'il ne soit trop tard.