Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Как удалить объект


Автор: LamerTM 11.9.2009, 22:04
Не получается удалить объект.


На форме кнопка и объект RichTextBox.

Код такой:

Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        WTC p;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            p = new WTC(richTextBox1);
        }

    }


    public class WTC
    {
        Timer timer = new Timer();
        RichTextBox rcb;
        static public int counter;
        int currentNumber;

        public WTC(RichTextBox x)
        {
            timer.Interval = 500;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Enabled = true;
            rcb = x;
            rcb.AppendText("Object created. Number: " + counter.ToString() + "\n");
            rcb.ScrollToCaret();
            currentNumber = counter;
            counter++;
        }

        void timer_Tick(object sender, EventArgs e)
        {
            rcb.AppendText("Timer called. Object number: " + currentNumber.ToString() + "\n");
            rcb.ScrollToCaret();
        }
    }
}


При нажатии на кнопку создается объект с таймером, который периодически пишет в richTextBox1, чем и показывает своё присутствие в памяти.
По идее, при создании нового объекта, предыдущий должен уничтожаться сборщиком мусора (по крайней мере так пишут на сайте майкрософт). У меня так не происходит и предыдущий объект не уничтожается, хотя ссылка на него вроде как теряется. Это видно после нескольких нажатий на кнопку. Созданные ранее объекты продолжают писать свои строки в richTextBox.
GC.Collect() не помогло.

Автор: Heinzz 11.9.2009, 22:15
Код

public partial class Form1 : Form
    {
        WTC p;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //*****************************
            if (p != null)
            {
                p.Dispose();
            }
            //*****************************
            p = new WTC(richTextBox1);
        }
    }
    public class WTC
    {
        Timer timer = new Timer();
        RichTextBox rcb;
        static public int counter;
        int currentNumber;
        public WTC(RichTextBox x)
        {
            timer.Interval = 500;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Enabled = true;
            rcb = x;
            rcb.AppendText("Object created. Number: " + counter.ToString() + "\n");
            rcb.ScrollToCaret();
            currentNumber = counter;
            counter++;
        }
        void timer_Tick(object sender, EventArgs e)
        {
            rcb.AppendText("Timer called. Object number: " + currentNumber.ToString() + "\n");
            rcb.ScrollToCaret();
        }

        //*****************************
        public void Dispose()
        {
            this.timer.Dispose();
        }
        //*****************************
    }


Добавлено через 5 минут и 45 секунд
ИМХО мусорщик не убирает созданные объекты поскольку таймер остался включен и к ним обращается.

Автор: LamerTM 11.9.2009, 22:24
О, не успел. Уже нашел решение на msdn. Хотел написать что проблема решена. Ну все равно спасибо.

Автор: Heinzz 11.9.2009, 22:24
а как решена?

Автор: LamerTM 11.9.2009, 22:31
Цитата(Heinzz @ 11.9.2009,  22:24)
а как решена?

Абсолютно также. smile Сам код лишь по виду чуть-чуть другой. Сделал таймер public, а в обработчик кнопки строку вписал так:
Код


 private void button1_Click(object sender, EventArgs e)
        {
            if (p != null) p.timer.Dispose();
            p = new WTC(richTextBox1);
        }



Об этом сказано в описании таймера: http://msdn.microsoft.com/ru-ru/library/system.threading.timer.aspx
Там еще что-то написано из того чего я не делал, а вроде надо было, но я пока не вникал.

Еще в класс добавил большой массив, чтобы по диспетчеру задач видеть как освобождается память (чтобы убедиться что не только таймер останавливается по Dispose, но и объект удаляется)

Автор: PashaPash 12.9.2009, 09:52
Цитата(LamerTM @  11.9.2009,  22:31 Найти цитируемый пост)
Абсолютно также.  Сам код лишь по виду чуть-чуть другой. Сделал таймер public, а в обработчик кнопки строку вписал так:

Лучше уж тогда сам WTC сделать Disposable. http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
Цитата(LamerTM @  11.9.2009,  22:31 Найти цитируемый пост)
Еще в класс добавил большой массив, чтобы по диспетчеру задач видеть как освобождается память (чтобы убедиться что не только таймер останавливается по Dispose, но и объект удаляется) 

Выставление в null и Dispose вообще-то не удаляет объект, и не освобождает память. Сборщик мусора - недетерменированный механизм, он может в тот же момент, а может вообще не собрать до завершения приложения.

Автор: EgoBrain 12.9.2009, 12:10
Цитата(PashaPash @ 12.9.2009,  09:52)
Выставление в null и Dispose вообще-то не удаляет объект, и не освобождает память. Сборщик мусора - недетерменированный механизм, он может в тот же момент, а может вообще не собрать до завершения приложения.

Получается в .NET любой вызов уничтожения объекта или приведение его в null лишь попытка обратить внимание сборщика мусора, то есть не единовременное освобождение?  smile (Если я конечно правельно понял цитату).

Автор: Heinzz 13.9.2009, 17:04
ИМХО нужно соблюдение условий - на объект нет действующих ссылок, его диспозят, других свободных ресурсов нет = железобетонно в мусор.

Автор: PashaPash 14.9.2009, 14:18
Цитата(EgoBrain @  12.9.2009,  12:10 Найти цитируемый пост)
Получается в .NET любой вызов уничтожения объекта или приведение его в null лишь попытка обратить внимание сборщика мусора, то есть не единовременное освобождение?  smile (Если я конечно правельно понял цитату). 

Отсутствие ссылок на объект - это лишь необходимое условие для освобождения памяти. Само особождение произойдет в какой-то неопределенный момент.
Где-то дальше в коде ты попытаешься создать какой-то новый объект. При попытке выделения памяти под него GC может решить что неплохо бы собрать мусор в 0-ом поколении. Построик список достижимых объектов. Все достижимые в 0-ом поколении переложит поплотнее в памяти, тем самым "собрав" недостижимые объекты.  Потом, если освободится маловато памяти, он соберет 1-е поколение. Потом, если после сборки 1-го, и если все еще мало памяти - то соберет 2-е.

Чем больше объект живет, тем больше у него шансов пережить сборки 0-го и 1-го и перейти во 2-е поколение. 2-е поколение собирается очень редко. Таймер в примере выше живет достаточно долго, и с большой вероятностью попадет в 1 или 2-е поколение.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)