Gen 2 memory leak caused by WPF TextBox?

4 篇文章 0 订阅
4 篇文章 0 订阅

Problem:

I wrote a small program several months ago, which is just as simple as pulling data from a server and then displaying it on UI. At that time I was studying WPF so I chose to use WPF to implement the UI. And because the area to display the data is very small, I used a disabled TextBox control instead of Lable control so that I can have scroll bars:

 

And I used TextBox.Text to update the TextBox in an every second basis from a non-UI thread.

The tool was running well but I noticed that after running for some time, it consumes more and more private bytes. I guess that there is some memory leak. But after reading through my code again and again (only 2 files) I am pretty sure that I don’t have any un-disposed objects. Confused and disappointed at my first WPF app I gave up because the increase in private bytes doesn’t affect my daily usage.

Today after work I opened ProcessExplorer to take a look at my processes. The application jumped into my eyes and its private bytes have grown into 200+ MB, which is ridiculous for such a small applet. I decided to do deeper analysis to find the root cause.

 

Analysis:

 

First thing I did is to use perfmon to check whether it is leak in managed heap or unmanaged heap. I checked Gen 0 to Gen 2 heap size, as well as private bytes. I immediately noticed that the Gen 2 heap is increasing as time goes by. See figure below.

PerfMon output

 

Apparently that there is something holding many objects for a long time. But why is that happening? I don’t have any code holding an object for a long time at all! With my mind full of doubt I took a dump of the application and used SOS to check the Gen 2 heap. I used some trick to scope dumpheap to only gen 2 objects:

 

 

I noticed that I have a lot of *ContentUndo* objects on Gen 2 and they consumes most of the memory. I quickly recalled that my code updates the TextBox every second. So are these *ContentUndo* objects related to the frequent update of the TextBox content? To verify this I picked up the object @0x000007fee3c42ef0 and tried to dump all elements of the undo stack out by iterating with !do command. Following is one of the element on the undo stack:

 

 

This string is exactly one of the status update strings I make to the TextBox control during pulling. It proves that the memory is mostly consumed by the undo history of the TextBox, which contains all historical changes I made to it every second. These data is held by the TextBox control so it enters Gen 2 heap as time went by and stayed there ever since. 

 

Resolution:

 

So is this a bug of TextBox control? After some research I noticed that WPF TextBox by default has UndoLimit set to –1, which means that all historical changes will be kept in memory. Somebody raised the same issue to Microsoft at here but MSFT claimed that this is a by design behavior, which personally I don't quite agree. How many developers know that endless updates to a WPF TextBox control can use up all the memory?!

 

The fix for this is easy though - I changed the UndoLimit of my TextBox to 0 and the issue disappears. The lesson I learned is that we need to pay attention to the default values of those controls and turn off those we don't need if it can potentially bring harm like this. But I do hope MSFT can fix it in the future.

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值