Как перетаскивание может повлиять на использование памяти в приложении Windows Forms?

Я столкнулся с странной ошибкой памяти в приложении Windows Forms, разработанном в Visual Studio 2010. Я использую C # и .NET 4.0, но не думаю, что это фактор здесь. Для воспроизведения запустите новое приложение Windows Forms и добавьте кнопку. Затем вставьте следующий код:

public Form1()
{
    InitializeComponent();
    AllowDrop = true;
    DragEnter += new DragEventHandler(Form1_DragEnter);
    button1.Click += new EventHandler(button1_Click);
}

private void Form1_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Link;
}

private void button1_Click(object sender, EventArgs e)
{
    for(int i = 1; i <= 100000; i++)
    {
        DataGridView dgv = new DataGridView();  // or any other large object
        if(i % 100 == 0)
            Console.WriteLine("{0}: {1} MB memory in use", i, Environment.WorkingSet / 1024 / 1024);
    }
}

Запустите программу, нажмите кнопку и посмотрите, как используется память в окне вывода. Он резко увеличивается, а затем падает, поскольку сборка мусора происходит в несколько циклов. Затем запустите его еще раз, перетащите любой случайный файл или папку в форму, пока не получите значок ссылки, а затем снова нажмите кнопку. На этот раз использование памяти должно монотонно увеличиваться, например, сборщик мусора не вызывается или все еще существуют действительные ссылки на все сгенерированные объекты.

Как установка курсора на эффект перетаскивания ссылки может повлиять на использование памяти таким образом ???


comment
Ваш вопрос действительно о Visual Studio или о C # / Winforms?   -  person Andrew Barber    schedule 04.05.2012
comment
Я полагаю, WinForms, но я почти уверен, что он не специфичен для C #.   -  person Craig W    schedule 04.05.2012
comment
Я хотел сказать, что вы говорите об утечке памяти в вашей программе, а не в Visual Studio. Какова величина памяти, о которой идет речь здесь, в каждом из моментов, которые вы упомянули в своем сообщении?   -  person Andrew Barber    schedule 04.05.2012
comment
Я пояснил, что это проблема WinForms, а не VS. И утечка памяти значительна, в данном примере несколько сотен МБ. В реальной ситуации, когда я столкнулся с этим, у меня быстро заканчивается память.   -  person Craig W    schedule 04.05.2012
comment
Я проверил, что это происходит. Однако, если вы сделаете DragDropEffects.None, это не вызовет утечки памяти.   -  person Moop    schedule 04.05.2012


Ответы (1)


Это известная утечка WinForms.
Происходит, когда для свойства AllowDrop установлено значение True.
Если вы установите значение False, среда CLR очистит память.
Лучший способ избежать этого - не использовать в качестве целевого контейнера для перетаскивания.

Вы можете использовать небольшую панель, например контейнер, который переключает свойство AllowDrop.

Это также будет работать:
При сбросе сбросить AllowDrop и принудительно выполнить сборку мусора.

void Form2_DragDrop(object sender, DragEventArgs e)
    {
        AllowDrop = false;
        GC.Collect();
        GC.Collect();
        AllowDrop = true;
    }
person Erez Robinson    schedule 29.05.2012
comment
Последнее решение, похоже, не помогло. Кроме того, есть ли у вас справочная информация, подтверждающая это как известную утечку WinForms? - person Craig W; 30.05.2012
comment
Я знаю об этой утечке уже некоторое время, но отслеживание ошибок Microsoft установило для нее значение «Не исправить», я не знаю почему. Я нашел только несколько сайтов, на которых обсуждается эта проблема, вы можете просмотреть эту страницу: stackoverflow.com/questions/ 620733 / memory-leak-in-c-sharp Но я настоятельно рекомендую не использовать форму в качестве места назначения, это все упростило бы. - person Erez Robinson; 19.06.2012