【问题标题】:WPF memory issueWPF内存问题
【发布时间】:2013-03-27 03:55:21
【问题描述】:

我正在尝试使用以下代码加载图片:

void LoadPictures(int s)
{
    grdScene.Children.Clear();
    TabControl tab = new TabControl();
    for (int i = s; i <= s+3; i++)
    {
        System.Drawing.Bitmap bmp = new System.Drawing.Bitmap("C:\\img\\" + i + ".png");
        TabItem tabItem = new TabItem();
        tabItem.Header = "Scene " + i;
        var bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(),
                                                                    IntPtr.Zero,
                                                                    Int32Rect.Empty,
                                                                    BitmapSizeOptions.FromEmptyOptions());
        Image image = new Image();
        image.Source = bitmapSource;
        tabItem.Content = image;
        tab.Items.Add(tabItem);
    }
    grdScene.Children.Add(tab);//grdScene is Grid
}

它工作正常,但每次我运行此方法时,内存都会增加。 然后我尝试将所有项目设置为null,但没有成功。代码如下:

foreach (var child in grdScene.Children)
{
    TabControl tab1 = (TabControl)child;
    foreach (TabItem item in tab1.Items)
    {
        Image img = (Image)item.Content;
        img = null;
    }
    tab1 = null;
}

我尝试了GC.Collect(),但没有任何改变。我应该怎么做才能解决这个问题?

【问题讨论】:

    标签: c# wpf memory memory-management memory-leaks


    【解决方案1】:

    你为什么要通过代码隐藏来做这个?

    从代码的外观来看,选项卡项完全由图像填充。

    您可以将一个 tabcontrol 绑定到图像路径集合并使用一种样式来描述您所追求的外观,这会简单得多,然后 WPF 核心将负责图像加载和内存管理自己。


    如果这对您不可用,那么您的问题来自您加载图像的方式,您是通过不安全的互操作方法进行的,不会为您释放内存,您必须处理位图你自己.Dispose()

    你最好这样做:loading the source of a BitmapImage in WPF?

    如果您想继续在代码隐藏而不是互操作方法中进行操作,使用 BitmapImage 可能是更好的方法。

    所以:

        void LoadPictures(int s)
        {
            grdScene.Children.Clear();
            TabControl tab = new TabControl();
            for (int i = s; i <= s + 3; i++)
            {
                BitmapImage bmp = new BitmapImage(new Uri("C:\\img\\" + i + ".png"));
                TabItem tabItem = new TabItem();
                tabItem.Header = "Scene " + i;
                tabItem.Content = new Image(){Source = bmp};
                tab.Items.Add(tabItem);
            }
            grdScene.Children.Add(tab);
        }
    

    应该做的伎俩。

    【讨论】:

    • 我使用 Bitmap 的原因是我的实际图片不在文件系统中。它存储在数据库中。在我的示例中,为了更容易,我只是从文件系统加载它。我正在考虑将二进制图片转换为位图并将位图转换为位图源。我想我可以直接从 byte[] 转换为 Windows.Controls.Image。我以前不知道。这样就解决了问题。感谢您的帮助!
    • @Dilshod 没问题,是的,您可以通过这种方式进行转换,但无论何时使用 System.Drawing 类或 WPF 互操作系统,请务必在所有内容上调用 .Dispose,它们是邪恶的类你会得到到处都是内存泄漏。
    【解决方案2】:

    尝试在所有IDisposables 上调用Dispose,例如System.Drawing.Bitmap 或更好地使用using..

    using(var bmp = new System.Drawing.Bitmap("C:\\img\\" + i + ".png"))
    {
         .....
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 2014-10-20
    • 1970-01-01
    相关资源
    最近更新 更多