拖放如何影响Windows Forms应用程序的内存使用?

4

我在使用Visual Studio 2010开发的Windows Forms应用程序中遇到了一个奇怪的内存错误。我正在使用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);
    }
}

运行程序,点击按钮,在输出窗口观察内存使用情况。随着垃圾回收多次进行,内存使用量会急剧上升然后下降。然后再运行一次,将任意文件或文件夹拖到表单上直到出现链接图标,然后再次点击按钮。这次内存使用量应该单调增加,就像垃圾回收没有被调用或所有生成的对象仍然有有效引用一样。
设置光标到链接拖放效果会如何影响内存使用情况呢???

你的问题是否真正与Visual Studio有关,还是与C#/Winforms有关? - Andrew Barber
WinForms 我想是指 Windows 窗体,但我很确定它不特定于 C#。 - Craig W
我的观点是,你似乎在谈论你的程序中的内存泄漏问题,而不是Visual Studio中的问题。在你帖子中提到的每个点上,这里涉及的内存规模是多少? - Andrew Barber
我已经澄清了这是一个WinForms问题,而不是VS。而且内存泄漏非常严重,在这个例子中有几百MB。在我遇到这个问题的实际情况中,我很容易就会耗尽内存。 - Craig W
我验证了这一点。但是,如果您使用DragDropEffects.None,则不会导致内存泄漏。 - Moop
1个回答

3
这是一个已知的WinForms泄露问题。
AllowDrop属性设置为True时会发生。
如果将其设置为False,CLR将清除内存。
避免此问题的最好方法是不要将表单用作目标拖放容器。
你可以使用类似容器的小面板来切换AllowDrop属性。
这也可以解决问题:
投放后,重置AllowDrop并强制垃圾回收。
void Form2_DragDrop(object sender, DragEventArgs e)
    {
        AllowDrop = false;
        GC.Collect();
        GC.Collect();
        AllowDrop = true;
    }

后一种解决方案似乎没有帮助。此外,您是否有记录这是已知WinForms泄漏的参考文献? - Craig W
我已经知道这个泄漏问题有一段时间了,但微软的错误跟踪设置为“不修复”,我不知道为什么。我只发现了一些讨论此问题的网站,您可以查看此页面:https://dev59.com/r3RB5IYBdhLWcg3wcm6d 但我强烈建议不要使用该表单作为放置目标,这将简化一切。 - Erez Robinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接