Problem:
If Handle count reaches more than 5000 count, whole PC might freeze and become unresponsive.
In the Event Log, you might have seen: “The server was unable to allocate from the system nonpaged pool because the pool was empty” message before system frozen.
This application had many wpf third party components, events and ui updates that were happening every 5 seconds, including tree updates. And it was leaking handles.
I verified that by cycling major logical parts, handle leak was not happening. But it happened when the whole flow was executed. When in debug mode, following the flow, leak does not happen. This was timing related.
Cause:
Short Story Shorter, this is how I fixed it. Calling GC.Collect(2, GCCollectionMode.Forced) on each cycle fixed the leak. Yes, you would say that eventually GC should collect the thread. Here is a relevant issue that other people reported. And Microsoft defect that had to do with how GC cleans up unused threads, this is what they say:
“The problem is that CLR thread handles (and other associated data structures) are cleaned up by the finalizer thread, which normally only runs in response to a garbage collection (GC). If many threads are created and destroyed before a GC occurs (which would be the case if there were few memory allocations in the meantime) then it has the effect of "leaking" handles and memory, althgough these will be reclaimed the next time finalization is triggered. A workaround is to periodically manually trigger finalization, through calls to GC.WaitForPendingFinalizers. As I said, we are working to correct this in a future CLR release.“ –Microsoft.
Solution 1:
So if you are in a long run leaking handles, see if GC.Collect(2, GCCollectionMode.Forced) fixes it. If not, then you deal with logical gaps. Readon further.
Solutions 2,3,4,..:
Possible Leak Causes:
- New Threads
- GDI objects, Images, Fonts,
What does NOT leak Handles:
- Extra subscriptions to Events do not lead to leaking Handles
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new ThreadStart((), does not leak handles. Verified.
Note:
Close or Dispose on StreamWriter related objects? In most cases, it is more appropriate to Dispose it instead of Close, it depends, see article Close vs. Dispose.
More about Handles.

