2015-12-17 2 views
0

В C#, я называю GC.Collect() в обоих Form1_Load и нажмите событиеТаблица данных выбрасывайте время

Вопрос не GC.Collect() кажется сделали ничего в Form_load

Но работает в случае щелчка. Зачем ?

GC.Collect() first time inForm1_Load

GC.Collect() second time inclick event

С Visual Studio 2015 диагностики инструмента

public partial class Form1 : Form 
     { 
      public Form1() 
      { 
       InitializeComponent(); 
      } 
      DataTable dt; 
      private void Form1_Load(object sender, EventArgs e) 
      { 
       dt = new DataTable(); 
       dt.Columns.Add("1", typeof(int)); 
       dt.Columns.Add("2", typeof(int)); 
       dt.Columns.Add("3", typeof(int)); 
       for (int i = 0; i < 1000000; i++) 
       { 

        DataRow dr = dt.NewRow(); 
        dr[0] = 10; 
        dr[1] = 1000; 
        dr[2] = 10000; 
        dt.Rows.Add(dr); 
       } 
       //gc first time 
       dt = null; 
       GC.Collect(); 
      } 

      private void button1_Click(object sender, EventArgs e) 
      { 
       //gc sec time 
       dt = null; 
       GC.Collect(); 
      } 
    } 
+1

Что вы пытаетесь достичь? Почему вы вызываете 'GC.Collect();'? – Irshad

+0

Пытаться удалить данные и получить память сразу – MaxJ

+0

Класс DataTable датируется .NET 1.0, когда Microsoft еще не так ясно представляла. Он наследует от MarshalByValueComponent, раннего дизайна дизайна quirk. Это дает ему финализатор, несколько особенный, поскольку он ничего не делает. Помимо сохранения памяти, занятой в первом вызове GC.Collect(). Он требует двух с вызовом GC.WaitForPendingFinalizers() между ними. Другой способ сделать это - сначала вызвать dt.Dispose(). Не делай этого. –

ответ

2

Чтобы позвонить GC.Collect это худшее, что вы можете сделать (как примерно 100% времени).

GC.Collect проверяет ссылочный счет объектов в памяти вашего приложения. Поскольку вы установили dt в значение null, ссылка на этот экземпляр DataTable не должна быть больше. Хорошо, поэтому сбор мусора «собирает» его. Но это означает только то, что он помещает его в очередь финализатора. Вы не вызывали dt.Dispose, который вызвал бы GC.SuppressFinalize(this), чтобы сообщить gc, что этот объект не нужно помещать в очередь финализатора.

Завершая этот объект для окончательной доработки, появляется новая ссылка на DataTable, и объект перемещается на одно поколение. В результате сбор мусора будет держать эту память еще дольше.

Вызвав GC.Collect второй раз в своем обработчике кнопок, вы делаете вещи еще хуже. Потому что снова все объекты, на которые все ссылаются, перемещаются на одно поколение и сохраняются еще дольше.

Вы просто должны распоряжаться DataTable по телефону dt.Dispose или заключая его в использовании заявление:

private void Form1_Load(object sender, EventArgs e) 
{ 
    using (DataTable dt = new DataTable()) 
    { 
     dt.Columns.Add("1", typeof(int)); 
     dt.Columns.Add("2", typeof(int)); 
     dt.Columns.Add("3", typeof(int)); 
     //... your code 
    } 
} 

И даже если вы сделаете это, пожалуйста, не называйте GC.Collect. Пусть сборщик мусора выполняет свою работу, поскольку он всегда лучше знает, как это сделать. Он освободит неиспользуемую память, если потребуется.

Для получения дополнительной информации см. Understanding Garbage Collection in .NET или this MSDN article.

+0

, еще один вопрос, почему в диагностическом инструменте vs2015, вызывая GC.Collect в щелчке событие действительно собирало память. – MaxJ

+0

Существуют различные режимы работы, в которых может работать сбор мусора.И поведение в режиме отладки снова меняется. Я не могу сказать, что именно происходит в вашем сценарии отладки. –

+0

Спасибо René Vogt, я использую сценарий по умолчанию в visual studio 2015, – MaxJ

Смежные вопросы