C# 以下XAML是否可能泄漏内存?

C# 以下XAML是否可能泄漏内存?,c#,wpf,C#,Wpf,我正在使用.NET4 WPF数据网格来显示一个包含大量图像的SQL表 所讨论的XAML代码是: ... <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Image Source="{Binding Converter={StaticResource ImageConverter}, Path=Picture}" Stretch="Uniform" MaxHeight="200" />

我正在使用.NET4 WPF数据网格来显示一个包含大量图像的SQL表

所讨论的XAML代码是:

...
<DataGridTemplateColumn.CellTemplate>
   <DataTemplate>
      <Image Source="{Binding Converter={StaticResource ImageConverter}, Path=Picture}" Stretch="Uniform" MaxHeight="200" />
   </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
...
我的问题是上面的代码是否泄漏内存?

我尝试过对此进行一些分析,但我不确定我是否正确解释了结果

首先,包含图像的SQL表使用38MB的磁盘空间(图像应以png格式存储)。在通过LINQ将所有图像加载到datagrid之后,该应用程序使用了大约170+MB的额外RAM。这可能有助于解压图像,而且即使启用了虚拟化,wpf数据网格也是一个巨大的内存占用器。关闭窗口后,内存使用率不会下降。重新打开该窗口将使用另外170+MB的RAM,使总内存使用量约为400MB。如果我再次打开窗口,那么内存使用量将下降到330MB左右。再次打开窗口将占用380MB的内存。重新打开需要270MB。重新打开需要426MB。所以,正如你所看到的,波动很大

这个小测试是用Win7x64和8GB的RAM完成的(这个应用程序是用任何CPU选项编译的)


我在虚拟xp机器上尝试了相同的测试,我认为代码中没有内存泄漏。虚拟机上的内存几乎立即下降这一事实意味着GC正在正确地执行其工作


在类似的情况下,我发现有一件事很有帮助,那就是在某处放置一个调用GC.Collect的按钮,并多次点击它。通常在“收集”死对象约3次后,如果不是这种情况,则可能发生泄漏。

可以通过
GC.GetTotalMemory(true)
确定内存是否写入页面文件。这将返回.NET进程的实际内存消耗,包括可能已写入页面文件的任何页面

这甚至可能与任务管理器报告的内存不同,但它将报告.NET对象实际分配的内存

有关任务管理器和
GetTotalMemory
报告的内存消耗差异的更多信息,请参阅


我的猜测是,
GC.GetTotalMemory(true)
将报告在收集之后所有内存实际上都已释放。

DataGridTemplateColumn的memoryleak问题似乎随.NET 4.5一起消失了。

我在一个按钮中尝试了您关于GC.Collect的建议,得到了一些奇怪的结果。首先,我在关闭窗口之后尝试了GC.Collect(),但没有得到任何结果(可能窗口没有超出范围)。现在,如果我按下按钮,大约80MB会立即释放,但大约100 MB不会。重复重新打开并按下按钮的过程,会产生与以前类似的结果-内存消耗波动很大。只有按下按钮后~80MB会立即释放。。。有什么想法吗?还是使用探查器来了解更多信息的唯一选择?我们在过去使用过,取得了很好的成功。它是免费的,使用起来也不难。顺便说一句,如果在点击GC.Collect之后释放了n次内存,这意味着即使n是一个非常大的数字,也没有泄漏。垃圾收集器是“懒惰的”(有充分的理由),并且可能会决定即使存在未引用的对象,也不需要释放资源。我将向Francesco给出答案,因为他首先给出了答案,但您的答案也非常好。GC.GetTeotalMemory确实报告了我的应用程序使用的正常内存量,即使任务管理器显示了更多120MB的内存。我猜这与你提供的链接中所说的有关——GC释放了内存,但没有将其释放到操作系统或类似的东西。太糟糕了,没有办法强制释放不必要的内存,我很乐意为2-3秒的GC工作付出代价。(让我想起了很多SQL日志文件,您必须手动缩小它以释放硬盘空间)无论如何,谢谢。太糟糕了,这里这么多的重点放在了第一个答案上,而不是正确的答案:)。因为我了解了GC.GetTotalMemy(我不知道),因为我偷了你的赏金;-)StackOverflow不允许设置多个答案,这有点令人失望,因为有时一个问题的完整答案是多个答案的总和。在这种情况下,我倾向于奖励第一个答案,尽管现在考虑一下,你的答案更完整(将答案改为对你有利,尽管我不知道这是否会恢复名誉)。。。下次我会更仔细地考虑;)
[ValueConversion(typeof(Binary), typeof(BitmapImage))]
public class ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.StreamSource = new System.IO.MemoryStream((value as Binary).ToArray());
            bi.EndInit();
            if (bi.CanFreeze) bi.Freeze();

            return bi;
        }
        else return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}