减少WPF应用程序内存消耗的方法[已关闭]

zujrkrfu  于 2022-11-18  发布在  其他
关注(0)|答案(1)|浏览(157)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新问题,以便editing this post可以用事实与引用来回答.

17天前关闭。
Improve this question
再见再见
我已经创建了一个小程序,创建调色板。这是好的,* 它的工作正确 *。Program Screenshot
整个代码是here。发布版本是here
创建的纹理在3D建模中用作材料。程序的工作原理如下:
1.用户选择颜色范围和色调。
1.程序迭代颜色,将当前颜色保存在矩形中。
1.将矩形放入堆栈面板(以便更好地管理)。
1.堆栈面板进入堆栈面板列表,然后进入画布。
1.画布显示在单独的窗口中。该画布必须可用于另存为图像。(原来是无用的功能)
我有一个小麻烦与这部分代码消耗了大量的内存。
例如,如果用户选择范围0-255,到步骤17,则将有3375个彩色框。(--(255 x255 x255)/(17 x17 x17)--)消耗70 mb。
如果用户选择范围0-255,到步骤5,则将有132651个颜色框。(--(255 x255 x255)/(5x 5x 5)--)消耗600 mb
有三个标记消耗的内存最多。当我第一次创建应用程序时,我假设在每个周期后,变量“rectangle”和“brushColor”都会被释放、垃圾收集和重用,但我完全错了。它们有WeakReference。
最后,我尝试缓存这些变量,但程序开始意外工作。最终窗口上没有颜色框或所有框都是一种颜色。或者这个“指定的Visual已经是另一个Visual的子级或CompositionTarget的根”。我无法在不破坏程序的情况下解决这些错误,所以我让它保持原样。
那么,在这种情况下,有什么更好的方法可以用来减少内存消耗呢?我的实现对我来说已经足够好了,但是我想知道我如何才能做得更好。也许我错过了一些明显的东西,或者相反,做了一些非常低效的事情,比如在矩形中存储颜色等等。

private void shuffle_colors1(List<StackPanel> stackPanels, Double colorBoxCount, int boxesInSingleRow, int stackPanelsCounter)
        {

            for (int redC = tempR; redC < crMax; redC++)
            {
                for (int greenC = tempG; greenC < cgMax; greenC++)
                {
                    for (int blueC = tempB; blueC < cbMax; blueC++)
                    {
                        var rectangle = new Rectangle(); // MARK 1
                        rectangle.Width = cBoxWidth;
                        rectangle.Height = cBoxHeight;
                        rectangle.Margin = border;

                        stackPanelColor = Color.FromRgb((byte)redC, (byte)greenC, (byte)blueC);
                         
                        brushColor = new SolidColorBrush(stackPanelColor); // MARK 2
                        displayedColors++;

                        rectangle.Fill = brushColor;
                        stackPanels[stackPanelsCounter].Children.Add(rectangle);
                        colorBoxCount++;
                           
                        if (colorBoxCount >= boxesInSingleRow)
                        {
                            AddNewStackPanel(stackPanels, stackPanelsCounter); // MARK 3
                            stackPanelsCounter++;
                            colorBoxCount = 0;
                        }
                              
                        blueC += bts - 1;
                    }
                   greenC += gts - 1;

                }
                redC += rts - 1;
            }
       }
tzdcorbm

tzdcorbm1#

如果不实际进行一些调试,很难判断实际的问题,但我可能会提供一些提示:

使用内存分析器

从你的描述看,你似乎已经这样做了,但是如果你确保清除了任何包含对矩形或任何其他UI对象的引用的东西,它们应该符合收集的条件。在你的示例代码中,我看不到任何确保堆栈面板被重新创建或清除的东西。
不删除事件处理程序是导致泄漏的另一个常见原因。
但也可能有bug。我遇到过一些问题,在应用程序本身释放了所有内容之后,Windows辅助功能仍然保留对UI元素的引用。Windows似乎在一段时间之后释放了引用,但我仍然认为如果在收集之后内存没有释放,这是一个bug。这种情况的症状是,当应该收集的UI对象只有一个可固定的句柄或groot作为根引用时,没有涉及用户代码。但是我找不到对这个问题的引用。

重用对象

Wpf对象的创建成本通常不是很低,因此您可能希望重用对象,而不是重新创建大量对象。只要您不更改框的数量,我看没有理由不简单地更新画笔的color property

限制使用的wpf元素数

虽然使用单独的UI元素对于一个较小的网格来说可能是合理的,但是130k元素听起来太多了。所以一个替代方案是将“音调步长”变量限制为某个合理的大值。
但是如果你想支持非常多的颜色,你可能会受益于使用WriteableBitmap来生成你想要的颜色布局,这样你的内存使用量就直接与你需要的像素数量成正比,而开销很小。
有些功能,比如鼠标悬停效果,可能会更复杂,但是大多数功能仍然可以通过在位图上使用常规的wpf元素来显示选择或任何你想要的东西。

相关问题