List <T>.Clear - Должен ли он быть вызван? - PullRequest
2 голосов
/ 20 июня 2010

Итак, я боролся с еще одной проблемой памяти в моем проекте на прошлой неделе. Я попробовал несколько профилировщиков памяти, но ничто не дало мне понять, что вызывает небольшую утечку памяти. Вызвал его следующий код:

private void DeleteAll( FlowLayoutPanel flp)
{
    List<ImageControl> AllList = GetAllList(flp);
    List<ImageControl> LockedList = GetLockedList(flp);

    for (int i = 0; i < LockedList.Count; i++)
    {
        AllList.Remove(LockedList[i]);
    }

    flp.SuspendLayout();

    for (int i = 0; i < AllList.Count; i++)
    {
        flp.Controls.Remove(AllList[i]);
    }

    DisposeList(AllList);

    flp.ResumeLayout();

}

В коде ImageControl является UserControl, а весь приведенный выше метод просто удаляет ImageControls из FlowLayoutPanel. Метод DisposList () просто вызывает ImageControl.Dispose () для всех переданных ему элементов управления в списке.

Теперь я подумал, что после выхода из этого метода AllList выйдет из области видимости и, следовательно, все его ссылки на ImageControl будут отсутствовать. Таким образом, GC сделает все это. Но это не так. Я нашел это требует

AllList.Clear();

добавлено в конец метода DeleteAll () до того, как AllList вышел из области видимости.

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

Хорошо, вот метод GetAllList. Для меня это не проблема:

private List<ImageControl> GetAllList(FlowLayoutPanel flp)
{
    List<ImageControl> List = new List<ImageControl>();

    for (int i = 0; i < flp.Controls.Count; i++)
    {
        List.Add((ImageControl)flp.Controls[i]);
    }

    return List;
}

Кстати, если вы видите мои последние пару тем здесь, я боролся с утечками памяти в своем стремлении стать опытным программистом на c # :) Я добавил метод DisposeList (), так как я прочитал, что Dispose () должен вызываться на любом объекте, который реализует IDisposable, что делает UserControl. Мне также нужен был способ исправить «ошибку» с классом ToolStrip (который содержит ImageControl), где он заставляет ресурсы оставаться, если свойство Visible не установлено в false, прежде чем оно будет уничтожено. Поэтому я переопределил метод Dispose ImageControl, чтобы сделать это.

Да, и DisposeList () также отписывается от обработчика событий:

private void DisposeList( List<ImageControl> IC )
{
    for (int i=0;i<IC.Count;i++)
    {
        IC[i].DoEvent -= ImageButtonClick;
        IC[i].Dispose();
    }
}

Ответы [ 2 ]

4 голосов
/ 20 июня 2010

Если бы AllList было единственной ссылкой на список и элементы в списке, то список и все его элементы стали бы пригодными для сборки мусора, как только вы выйдете из метода DeleteAll.

Если вызов AllList.Clear() имеет значение, то я бы пришел к выводу, что есть ссылка на тот же список, который содержится в другом месте вашего кода. Возможно, более внимательный взгляд на метод GetAllList () поможет понять, где.

1 голос
/ 20 июня 2010

Вам не нужно очищать список.Можете ли вы поделиться своей функцией GetAllList ()?Тот факт, что вам даже нужен соответствующий метод "DisposeList ()", говорит мне, что, возможно, там есть побочные эффекты, которые хранят ссылку на ваш список где-то.*

private void DeleteAll( FlowLayoutPanel flp)
{
    var UnlockedImages = flp.Controls.OfType<ImageControl>().Except(GetLockedList(flp));

    flp.SuspendLayout();

    foreach (ImageControl ic in UnlockedImages)
    {
        flp.Controls.Remove(ic);
    }

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