【问题标题】:A WPF transparent window doesn't dispose when closedWPF 透明窗口在关闭时不会释放
【发布时间】:2012-03-09 16:27:34
【问题描述】:

我在使用 WPF 构建的程序中发现了巨大的内存泄漏。我编写了一个小示例应用程序,它似乎在较小的范围内复制了这个问题。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        images = Directory.GetFiles("C:\\Photos", "*.jpg", 
                                                  SearchOption.TopDirectoryOnly);
        foreach (string image in images)
        {
            Window1 window = new Window1(image);
            window.Show();
            window.Close();
        }
    }
}

Window1 XAML 。 . .

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    AllowsTransparency="True"
    WindowStyle="None"
    Background="White"
    Opacity="1.0"
<Grid>
    <Image Name="pb_Image"/>
</Grid>

。 . .和 Window1 代码

public Window1(string image)
    {
        InitializeComponent();
        BitmapImage bi = new BitmapImage(new Uri(image, UriKind.Absolute));
        bi.Freeze();
        pb_Image.Source = bi;
        pb_Image.Height = bi.Height;
        pb_Image.Width = bi.Width;
    }

它反复显示然后关闭一个包含BitmapImage 的窗口,但是“内存不足异常”发生得非常快,所以我显然做错了什么,希望有人能指出!

* 更新 *

玩了一段时间后,我已经隔离了这个问题,这会导致内存泄漏:

foreach (string image in images)
        {
            Window1 window = new Window1(image);
            window.Show();
            window.Close();
        }

这不是

foreach (string image in images)
        {
            Window1 window = new Window1("C:\\Photos\\photo1.jpg");
            window.Show();
            window.Close();
        }

令人费解 - 有什么想法吗???

【问题讨论】:

  • Taskmgr 是一个非常不完美的内存分析器,垃圾收集器和 Windows 内存管理器都太复杂了,不能用一个数字来猜测。通过运行此代码一百万次来证明您确实遇到了问题。
  • 我已经更新了我的代码,希望能更准确地显示正在发生的事情。我怀疑我原来按比例缩小的代码没有准确地重现我遇到的问题。
  • @DavidePiras 谢谢,但我不确定需要处理哪些托管资源以及如何处理。
  • @Phil 这是在窗口 xaml 中定义的图像(见上面的编辑)

标签: c# wpf


【解决方案1】:

一旦你关闭了窗口,你仍然有一个对窗口对象的引用。关闭 window 后需要将其设置为 null。

【讨论】:

  • 删除对窗口的所有引用(例如设置window = null)只会使Window1 实例有资格进行垃圾回收。是否以及何时收集它并释放它的资源由垃圾收集器控制。按照 Hans Passant 的建议创建一百万个窗口,然后查看资源是否泄漏。
  • 我认为我按比例缩小的代码并未反映我实际遇到的问题,因此我对其进行了更新以更准确地显示正在发生的事情。
  • 您记得冻结位图,所以我看不出您的代码有任何问题(除非您的图像具有非常高的分辨率,例如 10,000 x 10,000)。正如 Martin 和 Hans 所说,TaskManager 不适合任何类型的内存分析。我以前使用过 Redgates Ants 内存分析器,发现它很容易使用,建议您下载试用版,以确定究竟是什么导致了您的内存泄漏。
  • @Gavimoss 最好使用 sos.dll。当你的程序启动时运行一个 dumpheap -stat,让它运行一段时间,然后运行另一个 dumpheap -stat。这将使您清楚地了解内存的使用位置。
【解决方案2】:

不知道为什么会发生上述内存泄漏,据我所知,一切正常。

我确实设法找到了这个excellent tutorial on "WPF Multithreading - Using the BackgroundWorker and Reporting the Progress to the UI",它很容易适应循环并显示一组图像,而不会出现任何内存泄漏问题。

【讨论】:

    猜你喜欢
    • 2013-01-02
    • 2015-01-23
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    相关资源
    最近更新 更多