C # удаляет элементы управления динамически, что это действительно делает? - PullRequest
0 голосов
/ 11 января 2019

Во-первых, отправьте сообщение, чтобы я оставил свой вопрос коротким.

Я добавил элемент управления на свою вкладку. Из-за ограничения наличия только одной переменной, но разных свойств имени. Я решил добавить все свои объекты текстового поля, которые я создаю в список. Текстовые поля создаются циклом.

Теперь, когда я удаляю их, я понимаю, что должен вызвать метод dispose. Я должен удалить элемент управления и, наконец, уменьшить число обработчиков событий.

Мой вопрос: что они на самом деле делают? Я ожидал, что мой список удаленных текстовых полей больше не будет существовать. Поэтому этот список должен либо стать пустым, либо выдать исключение, если я назову их свойства, такие как имя и т. Д.

Так почему же эти текстовые поля все еще в моем списке и все еще работают? Как будто я никогда не удалял их. Хотя они больше не в моей форме, кажется, они все еще живут в фоновом режиме, что может означать утечки памяти или замедление программы. Буду признателен за любые объяснения того, что делают эти методы и почему объекты текстового поля все еще существуют.

Последнее замечание, я из cpp. Поэтому, как я вижу, когда-то это вызывало удаление динамически создаваемых объектов, переменная больше не должна работать.

Кроме того, я могу добавить свой код, если требуется.

Редактировать: мой код выглядит следующим образом

  1. Для добавления на закладку:

    if (int.TryParse((sender as TextBox).Text, out int Stories))
    {
    
    
        Console.WriteLine(Stories); this.Stories = Stories;
        string L_name = "Label_";
        string T_name = "TextBox_";
        int counter = 1;
        int yIncr = Story_label.Size.Height + 3;//widthoftextbox+spacing
        List<string> L_name_arr = new List<string>
        {
            L_name + counter.ToString()
        };
        List<string> T_name_arr = new List<string>
        {
            T_name + counter.ToString()
        };
    
        for (int i = 0; i < Stories; i++)
        {
            //create new labels and textboxes below
            //have a max value.
    
            Label L_ = new Label();
            Model_Geometry_tab.Controls.Add(L_);
    
            L_.Location = new System.Drawing.Point(Story_label.Location.X, Story_label.Location.Y + yIncr * counter);//increasing increment every iteration
    
            L_.Name = L_name_arr[i];
            L_.Size = new System.Drawing.Size(Story_label.Size.Width, Story_label.Size.Height);
            L_.Text = "Story" + counter.ToString();
    
            TextBox T_ = new System.Windows.Forms.TextBox();
            //T_.BackColor = System.Drawing.SystemColors.ActiveBorder;
            T_.Location = new System.Drawing.Point(Story_input.Location.X, Story_input.Location.Y + yIncr * counter);
            T_.MaxLength = 1000;
            T_.Name = T_name_arr[i];
            T_.Size = new System.Drawing.Size(Story_input.Size.Width, Story_input.Size.Height);
            T_.KeyDown += new System.Windows.Forms.KeyEventHandler(TextBox_1_KeyDown);
            T_.MouseClick += new System.Windows.Forms.MouseEventHandler(textBox_other_MouseClick);
            T_.MouseHover += new System.EventHandler(textBox2_MouseHover);
            Story_arr.Add(T_);
    
            Model_Geometry_tab.Controls.Add(T_);
    
            //incr counter
            counter++;
            //addnewlabeltags
            L_name_arr.Add(L_name + counter.ToString());
            //addnewtexttags
            T_name_arr.Add(T_name + counter.ToString());
        }
    }
    else
    {
        MessageBox.Show("Enter an integer value please!");
    }
    
  2. Для их удаления я использую список Story_arr;

    private void button2_Click(object sender, EventArgs e)
    {
        if (Story_arr.Count != 0 && !a)
        {
            foreach (var item in Story_arr)
            {
    
                Console.WriteLine(item.Name);
                item.KeyDown -= new System.Windows.Forms.KeyEventHandler(TextBox_1_KeyDown);
                item.MouseClick -= new System.Windows.Forms.MouseEventHandler(textBox_other_MouseClick);
                item.MouseHover -= new System.EventHandler(textBox2_MouseHover);
                Model_Geometry_tab.Controls.Remove(item);
                item.Dispose();
            }
            a = true;
        }
        else if (a)
        {
            foreach (var item in Story_arr)
            {
                Console.WriteLine(item.IsDisposed);
            }
        }
        else
            MessageBox.Show("It is empty list");
    }
    

1 Ответ

0 голосов
/ 11 января 2019

Когда вы вызываете IDisposable.Dispose, это не значит, что объект удален. Утилизация объекта предназначена для очистки любых внутренних или внешних ресурсов. В WinForms это конкретно означает очистку любых основных дескрипторов окна и т. Д.

В управляемой памяти .NET только сборщик мусора в конечном итоге удалит объект. В вашем конкретном случае, однако, GC никогда не будет собирать ваши удаленные элементы управления, потому что они все еще есть в вашем списке. Наличие их в списке означает, что на объекты все еще ссылаются, т.е. они не мертвы. ГК будет собирать только мертвые предметы.

Просто удалите элемент управления из списка вручную, и все будет в порядке. Вы также можете прослушать событие Disposed элемента управления и удалить его из списка в обработчике событий. Это автоматически позаботится об удалении любого удаленного элемента управления из вашего списка.

Более сложным решением было бы не добавлять элементы управления непосредственно в список, а добавлять слабые ссылки. A WeakReference позволяет получить доступ к объекту, но не помешает сборке мусора. Однако я лично предпочел бы разыменовывать объект вручную, поскольку это более просто и менее подвержено ошибкам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...