2011/12/02

.NET Framework - Memory Leak เวลาใช้ System.Windows.Controls.Image

สวัสดีครับ เมื่อไม่กี่วันมานี้ผมเจอปัญหา Memory Leak ตอนใช้ System.Windows.Controls.Image ใน WPF มาครับ มาดูกันว่าผมทำยังไงมันถึงเกิดปัญหาขึ้น

ปัญหามีอยู่ว่า ผมโหลดภาพด้วย BitmapImage จำนวน 10 ภาพแล้วแสดงผลด้วย Image และผมต้องการที่จะลบภาพออก ปรากฏว่าเกิด Memory Leak ขึ้น โปรแกรมผมกิน Ram ไป เท่ากับตอนที่โหลดภาพ 10 ภาพ

เพื่อความสะดวกผมจะขอโหลดภาพขึ้นมาแค่ภาพเดียว เป็นไฟล์ png ขนาด 5.27MB ความละเอียด 1810x4034


public partial class MainWindow : Window
{
    Image img;

    public MainWindow()
    {
        InitializeComponent();
        img = new Image();
        stackPanel1.Children.Add(img);
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        var bi = new BitmapImage();
        bi.BeginInit();
        bi.UriSource = new Uri(@"H:\img.png");
        bi.EndInit();
        if (bi.CanFreeze)
            bi.Freeze();
        img.Width = bi.PixelWidth;
        img.Height = bi.PixelHeight;
        img.Source = bi;
        bi = null;
        img.Visibility = System.Windows.Visibility.Visible;
    }

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        img.Source = null;
        img.Visibility = System.Windows.Visibility.Collapsed;
    }
}

Code ข้างบนนี้เกิด Memory Leak


ผมลองเอา

img.Visibility = System.Windows.Visibility.Collapsed;

ออกปรากฏว่าปัญหา Memory Leak หายไป แต่ตัว Image ยังจองพื้นที่ใน Window อยู่จึงต้องกำหนดความกว้างกับความสูงเป็น 0 แทน

private void button2_Click(object sender, RoutedEventArgs e)
{
    img.Source = null;
    img.Width = img.Height = 0.0;
}

เท่านี้ก็ช่วยลด Memory ที่ใช้แล้ว ถึงจะลดได้ไม่หมด แม้ว่าจะลบ Image ออก แล้วใช้ GC.Collect() หน่วยความจำก็ไม่กลับคืนมาทั้งหมด
จะเห็นว่าตอนเปิดโปรแกรมใหม่ ๆ ใช้ Ram 14,596K
พอโหลดภาพมาแสดงใช้ Ram 72,984K
พอลบภาพออกจะใช้ Ram ลดลงเหลือ 45,032K

ตอนนี้ผมก็ยังไม่รู้จะแก้ได้ยังไง

No comments:

Post a Comment