Blog

Silverlight Memory Leaks and AutomationPeers

Using a memory profiling tool such as ANTS Memory Profiler from Red-Gate or MemProfiler from SciTech Software (I’m sure there others, but those were the only two I found that can profile a Silverlight Out-Of-Browser application) is a good idea.  By using such a tool, developers can discover a myriad of memory leaks and fix them before releasing their code.  These leaks usually stem from classes that attach event handlers to other classes.  In fact, in my opinion, I’ve seen more memory leaks in Silverlight (and WPF) stemming from poor event handler management than anything else.

However, every once in a while, you’ll see something that appears to be unexplainable.

After profiling an application for a client, I discovered the usual gambit of event-handlers and strong-references between objects.  In fact, an initial object retention graph (in this case, produced by the ANTS Memory Profiler) was almost indecipherable.

This is intentionally unreadable for two reasons: 1) to protect the innocent, and 2) because that graph is so big, there’s no way to actually show it in it’s entirety without massive scrolling (I could probably whip up a Deep Zoom for it, but that’s over kill for the purposes of this discussion).

The faint black box above the unreadable red “Start Here” box is the class I was researching, and the other boxes are classes in the hierarchy all the back to a GC root.  So, you can see that there were a lot.  After days of tracking down each strong reference and removing them, I ended up with a single chain.

This picture showed a ListBoxAutomationPeer as the last entity before being stuffed into the ManagedPeerTable.

My original object (the dark gray box) was never released and since this was one child view inside a parent container, multiple copies stayed in memory never to be garbage collected.

As far as memory consumption goes, it wasn’t too bad.  And since all the event handlers were removed, and all messages unsubscribed to, the object just floated in the ether being unobtrusive.  But, after spending days trying to clean up memory leaks, this was still unacceptable, especially since there were literally hundreds of these objects floating around.

The Automation framework was created as a method for adding accessibility or automated testing to your applications.  The AutomationPeers are the way your application can communicate with Automation clients, or the way the Automation clients can communicate with your application.

If an Automation Client is running, it can and will ask your application if it supports automation.  For both Silverlight and WPF this happens automatically (no pun intended).  Sometimes the client is nice about it and requires that you attach it to your application (like most automated testing frameworks).

In my case, I wasn’t running an automated testing framework.  I wasn’t creating an Automation Client at all and attaching it to my application.  But AutomationPeers were being created, nonetheless.

So, I tested this application on a co-workers machine to see if there was something environmental causing the problem.  As fate would have it, there was.  His computer was not showing this memory leak.

After a day or two of digging around I realized that my computer was running Tablet PC Input Services (I have a Wacom tablet and the Tablet PC Input Services was installed when Windows figured out I had pen-enabled computer).

Turning off the Tablet PC Input Services removed the AutomationPeers from the object retention graph and the memory leak was plugged.

Unfortunately, nothing in the ANTS Memory Profiler or MemProfiler indicated that Tablet PC Input Services was the culprit causing the AutomationPeers to be created.  Additionally, while it seems like I’m pointing a finger at TIPS, any AutomationClient would probably cause the same issues within the application.

In conclusion, when looking for memory leaks, be aware that the automation API can keep your objects alive for longer than you expect.   You can mitigate bugs this may cause by properly detaching objects from external events and removing strong references to existing objects when you dispose or unload them.  Finally, profile your application frequently as lots of things can show up that may help you fix issues before they escalate into week-long bug hunts.

Sergio Loscialo

View Comments

Recent Posts

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

6 days ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago

Mastering Compliance: The Definitive Guide to Managed Compliance Services

In the intricate landscape of modern business, compliance is both a cornerstone of operational integrity…

2 months ago