前段時間參與了一個WPF編寫的項目,在該項目中有這樣一個場景:在程序運行過程中需要動態地產生大量文本信息,並追加WPF界面上的一個TextBox的Text中進行顯示。編寫完之后,運行該項目的程序,發現在產生大量信息之后,發現系統變慢了,打開任務管理器才發現,該項目的程序占用了將近1.5G的內存(天啊!!!這不是一般的耗內存啊!!!)。后來通過查資料和探索才發現了WPF的TextBox在追加Text顯示文本時會造成內存泄露。下面通過一個小Demo程序來展示一下這個內存泄露。
我的Demo程序很簡單,就是在界面上顯示一個TextBox和一個Button,點擊Button后就從0到9999進行for循環並將這些數字追加的TextBox的Text中進行顯示。代碼如下,

<Window x:Class="TextBoxMemoryLeak.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="測試TextBox內存泄露" Height="350" Width="525" WindowStartupLocation="CenterScreen"> <Grid Margin="5"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="35" /> </Grid.RowDefinitions> <DockPanel Grid.Row="0"> <TextBox Name="tbOutput" IsReadOnly="True" VerticalScrollBarVisibility="Auto"/> </DockPanel> <StackPanel Grid.Row="1" FlowDirection="RightToLeft" Orientation="Horizontal"> <Button Name="btnStart" Content="開 始" Margin="5,4,5,4" Width="65" Click="btnStart_Click" /> </StackPanel> </Grid> </Window>

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace TextBoxMemoryLeak { /// <summary> /// MainWindow.xaml 的交互邏輯 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void btnStart_Click(object sender, RoutedEventArgs e) { this.btnStart.IsEnabled = false; this.tbOutput.Text = ""; for (int i = 0; i < 10000; i++) { //使用此語句進行Textbox的追加會造成內存泄露 //this.tbOutput.Text += string.Format("{0}\n", i); //使用此語句進行Textbox的追加可避免內存泄露 this.tbOutput.AppendText(string.Format("{0}\n", i)); } this.btnStart.IsEnabled = true; } } }
界面如下所示:
內存泄露情況
最初我們采用的是TextBox的Text追加方式如下
this.tbOutput.Text += string.Format("{0}\n", i);
構建,啟動調試后,我們查看任務管理器,此時所占內存只有16M,
點擊【開始】按鈕之后,等到從0輸出到9999之后,我們再查看任務管理器,發現此時所占的內存飆到了600+M,
若此時再點擊【開始】按鈕,等循環結束,發現所占內存飆到了900+M,
再點擊【開始】按鈕的話,就要發生OutOfMemory異常的。當我們將循環改為從0到19999時,第一次點擊【開始】按鈕,我的機器就發生OutOfMemory異常了。
避免內存泄露的情況
將TextBox的Text追加方式改為下面語句
this.tbOutput.AppendText(string.Format("{0}\n", i));
構建,啟動調試,然后點擊界面的【開始】按鈕,等循環結束,我們查看任務管理器,測試Demo程序只占了29M內存(此時是從0到19999的循環)。