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.
fivesecondtest.com, "A simple online usability test that helps you identify the most prominent elements of your user interfaces."
Simple yet great idea.
Here is an example: Help me improve a design I'm working on by doing a five second test.
I've just moved the LINQ tools referenced on SharpToolbox.com to a new dedicated LINQ category.
20 tools and providers are listed for the moment. I'll add more shortly.
See Jim's blog for more resources.
Cross-posted from http://linqinaction.net
Ten years ago, I played with OLE Automation so we can write things such as the following, where Document represents an XML document:
String name = Document.Bookstore.Book[1].Author.LastName;
Document.Bookstore.Book[1].Author.LastName = "NewName";
The experiment was named XMLAuto.
I wanted to implement this again with C# 4's dynamic keyword, but I won't have to do it. Mark Michaelis and Michael Stokesbary already played with this (last year).
I find it's an interesting way to learn how to implement IDynamicObject.
Update: See also this article about the ExpandoObject and this article about DynamicObject.
Given my own experience, I'd say that events are the main source of leaks in .NET. They deserve double- and even triple-checks. Each time you add a subscription to an event in your code, most likely with +=, you should worry about the consequences and ask yourself whether you need to add a -= somewhere to unsubscribe from the event. If you have to, do it immediately before you forget about it. Often, you'll do that in a Dispose method.
Don't forget that subject objects keep the observer (or listener, or subscriber) objects that observe them alive. See this post of mine if you need a refresher about the subject.
Having listener objects unsubscribe from the events they subscribe to is usually the recommended way to ensure they can be collected. However, when you absolutely know that a subject object wont publish notifications anymore and you wish that its subscribers can be released, you can force the removal of all the subscriptions to the subject object. Here is how this can be achieved:
if (SomeEvent != null)
{
foreach (EventHandler handler in SomeEvent.GetInvocationList())
SomeEvent -= handler;
}
Update: As suggested by Steve in a comment, SomeEvent = null is enough!
Update: I've improved the sample source code to show if the listeners are dead or alive.
Update: See also this new article of mine.
I have a code sample available for you to download.
"Error creating window handle"
When a big Windows Forms application I'm working on for a client is used actively, users often get "Error creating window handle" exceptions.
Aside from the fact that the application consumes too much resources, which is a separate issue altogether that we are already addressing, we had difficulties with determining what resources were getting exhausted as well as what the limits are for these resources.
We first thought about keeping an eye on the Handles counter in the Windows Task Manager. That was because we noticed that some processes tended to consume more of these resources than they normally should. However, this counter is not the good one because it keeps track of resources such as files, sockets, processes and threads. These resources are named Kernel Objects.
The other kinds of resources that we should keep an eye on are the GDI Objects and the User Objects. You can get an overview of the three categories of resources on MSDN.
User Objects
Window creation issues are directly related to User Objects.
We tried to determine what the limit is in terms of User Objects an application can use.
There is a quota of 10,000 user handles per process. This value can be changed in the registry, however this limit was not the real show-stopper in our case.
The other limit is 66,536 user handles per Windows session. This limit is theoretical. In practice, you'll notice that it can't be reached. In our case, we were getting the dreaded "Error creating window handle" exception before the total number of User Objects in the current session reached 11,000.
Desktop Heap
We then discovered which limit was the real culprit: it was the "Desktop Heap".
By default, all the graphical applications of an interactive user session execute in what is named a "desktop". The resources allocated to such a desktop are limited (but configurable).
Note: User Objects are what consumes most of the Desktop Heap's memory space. This includes windows.
For more information about the Desktop Heap, you can refer to the very good articles published on the NTDebugging MSDN blog:
Desktop Heap Monitor (dheapmon.exe)
It's possible to monitor the Desktop Heap usage thanks to a command line tool: Desktop Heap Monitor (dheapmon.exe).
It would be interesting to monitor this usage directly from within applications to prevent crashes. We could let users know that all the resources are about to be exhausted, and ask them to close windows and prevent them from opening new screens. This would help to avoid the "Error creating window handle" errors. When these exceptions occur, it's difficult to handle them gracefully and it's often too late to react because the application is in an unstable state.
Unfortunately, it's not possible to consult the usage of the desktop heap programmatically from an application. The dheapmon.exe tool is based on a kernel mode driver (a .sys file) for collecting the data it returns.
A solution could be to create a new desktop, dedicated to the application. In practice, this is not viable though because only one desktop can be visible at a time.
Another solution is to increase the size of the Desktop Heap. We can, for example, replace the second value by default of SharedSection (3072) by 4096. Yay, more resources to waste!
What's the real solution? Be green!
Increasing the Desktop Heap is an effective solution, but that's not the ultimate one. The real solution is to consume less resources (less window handles in our case). I can guess how disappointed you can be with this solution. Is this really all what I can come up with??
Well, there is no big secret here. The only way out is to be lean. Having less complicated UIs is a good start. It's good for resources, it's good for usability too. The next step is to avoid waste, to preserve resources, and to recycle them!
Here is how we're doing this in my client's application:
- We use TabControls and we create the content of each tab on the fly, when it becomes visible;
- We use expandable/collapsible regions, and again fill them with controls and data only when needed;
- We release resources as soon as possible (using the Dispose method). When a region is collapsed, it's possible to clear it's child controls. The same for a tab when it becomes hidden;
- We use the MVP design pattern, which helps in making the above possible because it separates data from views;
- We use layout engines, the standard FlowLayoutPanel and TableLayoutPanel ones, or custom ones, instead of creating deep hierarchies of nested panels, GroupBoxes and Splitters (an empty splitter itself consumes three window handles...).
The above are just hints at what you can do if you need to build rich Windows Forms screens. There's not doubt that you can find other approaches.
The first thing you should do in my opinion is building your applications around use cases and scenarios. This helps in displaying only what's needed at a given time, and for a given user.
Of course, another solution would be to use a system that doesn't rely on handles... WPF anyone?
After English, German, Spanish, and Portuguese, LINQ in Action is now available in Chinese (中文).
The title is LINQ实战. The publisher is 人民邮电出版社 (Posts & Telecom Press). The book is also available on Amazon.cn/joyo and several other bookstores.
In addition to all the translations, LINQ in Action has been republished in English in India by DreamTech Press.
Cross-posted from http://linqinaction.net
I have a free one-year MSDN subscription to offer. I believe that it has to be activated before June 30, so, I don't have time to organize a contest or something...
The offer is MSDN Premium, which gives you access to a whole set of Microsoft software licensed for design, development, testing, and demonstration of your programs. This includes Visual Studio Team Suite, Windows, Office, SQL Server, etc. Given the releases expected this year, this will give you access to such things as Visual Studio 2010 and Windows 7.
If you think that you deserve to get this subscription, just contact me and let me know why I should give YOU this gift. I'll make my choice quickly and I'll reply to you.
Hint: if you can help me update the content of SharpToolbox.com, that can be a plus for you ;-)
UPDATE: We have a winner! Thanks to everyone who participated. I'll reply shortly to each one of you.
After we published the code samples for LINQ in Action's first chapters in LINQPad a few weeks ago, the samples of three more chapters have just been added. These chapters cover LINQ to XML. Thanks Jim for doing the additional conversion.
The code samples for chapters 1 to 11 are now available. Read the original announcement to learn how to download and use these samples. A new download is enough to get the update.
Cross-posted from http://linqinaction.net
Do you know LINQPad? It's a really simple but great tool for testing LINQ queries. Not only that, but it can be used to test all kinds of C# and VB code snippets.
Another great thing about LINQPad is that it comes with code samples. Until now the integrated code samples came from the C# 3.0 in a Nutshell book. Joe Albahari, author of LINQPad and C# 3.0 in a Nutshell, has opened LINQPad so that code samples from other books can be integrated into LINQPad. Thanks Joe for this opportunity!
We worked with Joe to integrate LINQ in Action's code samples into LINQPad. The result is that in addition to being available as Visual Studio solutions and projects, you can now run our code samples directly from LINQPad. This makes it very easy to explore LINQ's features with instant "code and play".
To install LINQ in Action's code samples in LINQPad, all you have to do is click on the "Download more samples..." link:
You'll see LINQ in Action proposed as one of the LINQPad-enabled books (the only one at the moment, in fact):
Once you've clicked on "Download full code listings into LINQPad", you should see the C# and VB samples grouped by chapter:

Currently, chapters 1 to 8 are available. We'll integrate the remaining code samples soon.
Have fun with LINQ!
Cross-posted from http://linqinaction.net
More Posts
Next page »