問題源自這篇文章:WPF的TextBox產生內存泄露的情況。
整個問題是這樣的,文章作者演示使用類似下方的代碼來不停地像WPF的TextBox控件賦值:
for (int i = 0; i < 10000; i++)
{
//tbx是界面上的TextBox變量
tbx.Text += string.Format("{0}\n", i);
}
然后會出現程序占用過多內存的問題。
很快在那篇文章的評論中有人指出這個和WPF沒有關系,因為頻繁得拼接字符串會產生過多重復字符串對象,即使不顯示在TextBox控件上,也會會占用過多內存的。
但是原文作者又在回復中講到他做了相關測試,但是卻不會出現占用非常多的內存的情況。
最后問題不了了之。
我做了下測試,一種是不斷拼接字符串並顯示在TextBox中:
//我們就拿個小數字1萬來做示例
for (int i = 0; i < 10000; i++)
{
//tbx是界面上的TextBox變量
tbx.Text += string.Format("{0}\n", i);
}
程序運行后任務管理器顯示55.5 MB的內存。(環境:.NET 4.5/Debug編譯/64位)
接着測試另一種情況:先拼接字符串,最后才顯示在TextBox中:
var str = String.Empty;
//我們就拿個小數字1萬來做示例
for (int i = 0; i < 10000; i++)
{
//tbx是界面上的TextBox變量
str += String.Format("{0}\n", i);
}
tbx.Text = str;
運行后顯示24.1 MB。
如果把最后一句刪掉,也就是根本不在TextBox中顯示。運行后是23.4 MB。
很明顯,整個問題確實是和WPF有關系的,但也不是因為原文作者認為的字符串拼接所造成的。真正的問題是TextBox(更准確地說是其父類:TextBoxBase)的UndoLimit屬性。也就是說TextBox會因為頻繁修改值而堆積過多的撤銷項目項目。
這部分項目會占用過多的內存空間。
在.NET 3.5和4.0:TextBoxBase.UndoLimit的值默認是-1。代表如果內存夠用的話,撤銷列表會無限大。(這個有點恐怖)
在.NET 4.5中:TextBoxBase.UndoLimit的值默認是100。
我們可以吧TextBoxBase.UndoLimit設置成0(或者把IsUndoEnabled設置成False),也就是命令TextBox不支持撤銷功能。再次運行第一次的代碼:
//禁止撤銷
tbx.UndoLimit = 0;
for (int i = 0; i < 10000; i++)
{
//tbx是界面上的TextBox變量
tbx.Text += string.Format("{0}\n", i);
}
運行后,任務管理器顯示29.4 MB(幾秒后又變成了24 MB)。而沒有設置UndoLimit,也就是.NET 4.5中默認值是100的情況下,占用內存則能飆升到55.5 MB。在非.NET 3.5或者4下可能會更大,因為默認是沒有限制的。
那么問題的解決方案是:
適當設置WPF的TextBox.UndoLimit(尤其是.NET 3.5/4.0環境下,默認值-1太可怕了)。當然這僅僅應用在頻繁設置TextBox值的情況下,如果沒有此類情況,無需擔心。另外也要注意如果要進行頻繁字符串拼接操作,請使用TextBoxBase.AppendText或者StringBuilder。
本文來自劉圓圓博客,原文地址:http://www.cnblogs.com/mgen/archive/2013/02/24/2924558.html
