如何释放新类使用的内存以避免内存泄漏?

时间:2015-05-13 13:26:32

标签: c# wpf memory memory-leaks backgroundworker

我正在使用以下代码。正如我在.Net内存分析器中看到的那样,我发现内存泄漏正在发生。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.ComponentModel;
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 TestMemLeak
 {
 public partial class MainWindow : Window
  {

    public int count = 0;
    BackgroundWorker worker = new BackgroundWorker();
   public  class test 
    {
        public int sno{get; set;}
        public string col1 { get; set; }
        public string col2 { get; set; }
        public string col3 { get; set; }
        public string col4 { get; set; }
        public string col5 { get; set; }
        public string col6 { get; set; }
        public string col7 { get; set; }

    }
  // test test1 = new test();
    public MainWindow()
    {
        InitializeComponent();
        worker.WorkerReportsProgress = true;           // For Background Worker
        worker.DoWork += worker_DoWork;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerSupportsCancellation = true;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    }


    private void Load_Click(object sender, RoutedEventArgs e)
    {
        dg1.Items.Clear();
        worker.RunWorkerAsync();
    }
    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
       // int max = (int)e.Argument;

        for (int i = 1; ; i++)
        {
            (sender as BackgroundWorker).ReportProgress(i);
           System.Threading.Thread.Sleep(1);


            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }
    }
    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        int i = e.ProgressPercentage;


        if (i > 100000)
        {
            count++;
            if (count == 100)
            {
                for (int k = 0; k < 100; k++)
                { dg1.Items.RemoveAt(0); }
                count = 0;
            }
        }

            dg1.Items.Add(new test() {sno=i,col1="test",col2="test",col3="test",col4="test",col5="test",col6="test",col7="test" });



    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            System.Windows.MessageBox.Show("Task Cancelled.....");
        }

            // Check to see if an error occurred in the background process.

        else if (e.Error != null)
        {
            System.Windows.MessageBox.Show("Error while performing background operation." + e.Error.Message);
        }
        else
        {
            // Everything completed normally.
            System.Windows.MessageBox.Show("Task Completed..." + e.Result);
        }
    }

    private void Stop_Click(object sender, RoutedEventArgs e)
    {
        worker.CancelAsync();

    }

    private void Clear_Click(object sender, RoutedEventArgs e)
    {
      //  worker.CancelAsync();
        dg1.Items.Clear();
       // GC.Collect();
    }
}
}

每次我创建一个新的类测试时,都会占用内存并且不会被GC释放。我怎么能避免这个?

2 个答案:

答案 0 :(得分:0)

我看到您注册了这些事件:

worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;

您需要在某个时候取消注册。为此,您可以在类中实现IDisposable接口,并取消注册Dispose函数中的事件。像这样:

public partial class MainWindow : Window, IDisposable
{

...

    public void Dispose()
    {
        worker.DoWork -= worker_DoWork;
        worker.ProgressChanged -= worker_ProgressChanged;
        worker.RunWorkerCompleted -= worker_RunWorkerCompleted;
    }
}

您也可以将BackgroundWorker设置为null,以防万一。

答案 1 :(得分:0)

取消订阅活动时

通常,如果事件属于不同的类别或者发布者的寿命超过订阅者,则需要取消订阅事件。在这里,backgroundWorker是您的类变量,其生命周期范围等于此类实例生命周期。因此,无需取消订阅这些事件处理程序。

何时实施IDisposable

如果您有任何已实现IDispose接口的类变量,则应实现IDisposable pattern。如果你有任何具有Dispose方法的类变量,你应该实现IDispose接口和Dispose所有一次性对象。

在您的代码中

显然,您的视图中有一些一次性对象(具有Dispose方法的对象)。 (我认为至少DataGrid是一次性的)实现IDisposable接口并处理所有一次性对象。

确保在实现IDisposable模式后调用Dispose方法!只是实施它没有任何影响。