Как плъзгането и пускането може да повлияе на използването на паметта в приложение на 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. И изтичането на памет е значително, няколкостотин MB в примера тук. В ситуацията от реалния свят, в която се сблъсках с това, лесно ми изчерпва паметта.   -  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 го настрои на Won't Fix, не знам защо. Намерих само няколко сайта, обсъждащи този проблем, можете да видите тази страница: stackoverflow.com/questions/ 620733/memory-leak-in-c-sharp Но силно препоръчвам да не използвате формуляра като дестинация за изхвърляне, това би опростило всичко. - person Erez Robinson; 19.06.2012