Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF RichTextBox memory leak

In my application, I have a lot of RichTextBoxes that are created dynamically in run time. I realized that the application has a memory leak, which is caused by the RichTextBox controls. To prove that the memory leaks because of the control I wrote the following test method:

for (int i = 0; i < 3000; i++)
        {
            Control rich = new RichTextBox();
            pnl.Content = rich;
        }
GC.Collect();
GC.WaitForPendingFinalizers();

pnl is a ContentControl that is declared in Xaml code.
If you run the following code, you can see that the memory usage is growing rapidly.

Any ideas how to solve the problem? I considered creating an object pool, but this would complicate my application, and I rather avoid it.


edit: I've added call to the garbage collector to demonstrate that the objects are not garbage collected - there is no improvement in the memory usage with and without the call to the GC collect method. Note that calling rich.Dispose within the loop eliminates the memory usage growth.

like image 485
Elad Avatar asked Oct 26 '09 15:10

Elad


2 Answers

This isn't an indication that your application has a memory leak, it's an indication that your application is using a lot of memory. It's a leak if the RichTextBox controls don't get released at some point after they've fallen out of scope (detecting memory leaks on managed objects is notoriously difficult and unprovable).

A common misconception that an object falling out of scope will cause it to be garbage collected. This just makes it eligible to be collected. The object may theoretically never be collected until the application terminates. The fact that it grows with RichTextBox and not with other controls is not an indication that there is a memory leak in the RichTextBox, it's just an indication that it uses more memory per instance than other controls. While this information may be useful, it doesn't help when determining whether or not there's a memory leak.

like image 142
Adam Robinson Avatar answered Oct 07 '22 15:10

Adam Robinson


Found this elsewhere, and it seems to be correct as far as my testing is concerned.

When a FlowDocument is created, relatively expensive formatting context objects are also created for it in its StructuralCache. When you create multiple FlowDocs in a tight loop, a StructuralCache is created for each FlowDoc. Let's you called Gc.Collect at the end of the loop, hoping to recover some memory. StructuralCache has a finalizer releases this formatting context, but not immediately. The finalizer effectively schedules an operation to release contexts at DispatcherPriority.Background.

So the RichTextBox (or FlowDocument) in case is not leaking just waiting on a background thread to cleanup. When it runs exactly who knows. I wish this just implemented a dispose method that would force a cleanup immediately.

like image 25
Kelly Avatar answered Oct 07 '22 14:10

Kelly