【问题标题】:WPF multiple controls OutOfMemoryWPF 多个控件 OutOfMemory
【发布时间】:2015-07-07 12:58:13
【问题描述】:

我自己做了一个控件来“伪造”一个细节网格。每一行都是一个单独的控件,这意味着我需要很多。我正在尝试将它们存储在位于 ScrollViewer 中的 StackPanel 中。

当我添加一个控件时,我的可执行文件的内存使用量上升了 10mb。当我尝试使用绘制所有 110 个数据包时,它会攀升至 1.5GB 并引发 OutOfMemory 异常。

控件非常简约。没有执行,只有几个标签、一些矢量图形、一个扩展器和一组 3 个控件(只有多个标签)。

我该如何解决这个问题?

【问题讨论】:

  • 为什么你首先要“伪造”一个网格?
  • 您可以发布控件吗?我做了类似的事情(尽管控制更简约),没有任何问题显示 + 数千个
  • 我建议在您的自定义控件中实现虚拟化,以确保它只呈现可见项目(它会在您滚动并替换它们后面的 DataContext 时重新使用控件),并考虑使用基本的除当前具有用户焦点的项目之外的所有项目的单元格模板。我曾经为减少 Grid 中的内存使用所做的一个基本示例是将每个项目显示为基本 TextBlock,并且仅在用户将焦点设置在单元格上时将其替换为 TextBox。
  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误在问题本身中重现它所需的最短代码。没有明确的问题陈述的问题对其他读者没有用处。见:How to create a Minimal, Complete, and Verifiable example.
  • @Rachel:虚拟化不是我最喜欢的解决方案,但我会尝试一下。

标签: c# wpf memory user-controls out-of-memory


【解决方案1】:

作为一个快速修复,你可以试试这个代码,它会立即释放内存

 /// <summary>
    /// Memory Management
    /// </summary>
    public class MemoryManagement
    {
        /// <summary>
        /// Clear un wanted memory
        /// </summary>
        public static void FlushMemory()
        {
            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                {
                    SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
                }
            }
            catch (Exception e)
            {
            }
        }

        /// <summary>
        /// set process working size
        /// </summary>
        /// <param name="process">Gets process</param>
        /// <param name="minimumWorkingSetSize">Gets minimum working size</param>
        /// <param name="maximumWorkingSetSize">Gets maximum working size</param>
        /// <returns>Returns value</returns>
        [DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet =
          CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
    }

【讨论】:

    【解决方案2】:

    您似乎想要为每个单元格设置一个特定模板。您应该使用项目控件及其模板来帮助您实现这一目标,请查看此处 is there a datatemplate for grid panel elements in WPF?、此处 WPF - Display single entity with a data template 和此处 ItemsControl ItemTemplate Binding 以获取示例以及有关如何使用它们的更多信息。

    【讨论】:

    • 我会尝试改进我的应用程序。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    相关资源
    最近更新 更多