所以我想制作一个包含动态控件布局的程序,有点类似于网页。 我有一个特定的按钮,如果您单击它,它应该会处理所有当前可见的控件,并使用第二个 InitializeComponent 加载一组完整的新控件。
第二个页面将包含一个“后退”按钮,该按钮应该用于处理第二组控件,并再次使用第一个 InitializeComponent 重新加载原始控件,这样我就有了 2 个不同的可访问“页面”。
但是,每次我通过按钮切换并再次调用InitializeComponent时,VRAM使用量都会稳步增加,可能是因为它并没有真正通过dispose“杀死”所有以前的资源。
所以我想问是否有一种方法可以重新加载已处理的初始化控件,而不必再次初始化它们。
提前致谢。
编辑: 啊,没关系,我明白了。
而不是 .dispose 我只是使用 Controls.Remove 命令在更改到第 2 页时删除当前的控件集。 如果我想返回,我现在可以简单地使用 Controls.Add 命令再次查看第一组控件,并且 VRAM 使用量不会增加。
这对于处置来说是不可能的,有人愿意解释一下吗?我是 csharp 的真正初学者,基本上是几天前开始的。
实际上你不应该自己调用Dispose()。通常,当您在表单上调用 Close() 等时,框架会为您执行此操作。 显然,如果仍然存在对各个元素的引用,这并不总是会导致相应元素被删除。这就是您的控件在某种程度上仍然存在的原因。
如果您(由于某种原因)需要 Close() 或 Remove() 以及您保留引用的元素,您应该在执行其他操作之前执行 element.IsDispose 检查。如果这是真的,你应该重新创建它,因为该元素已经半死了。请不要使用死灵术:-)
在任何一次性对象上调用
Dispose
应导致其释放(将引用设置为 null)任何引用的一次性对象,并清理任何直接引用的非托管资源。对于 UI 控件,处置将释放非托管的底层 Win32 GUI 对象。 Dispose 并不是释放内存以供重用,这是当对象没有被某些静态或堆栈(本地)引用(间接)引用时由垃圾收集器完成的。如果您保留对最后一页(要返回)的引用,则其 Controls
集合中的控件仍将被引用并保持活动状态。即使它们从控件集合中删除并且未被引用,由于 UI 控件往往会存在一段时间,它们很可能已经从第 0 代(经常收集)转移到第 1 代甚至第 2 代(很少收集)。除非存在内存压力(您的系统没有太多可用内存),否则可能需要很长时间才能收集它们。
您可以通过使用带有 SOS 扩展的 WinDbg 查看特定对象所在的世代(甚至列出该世代中的所有对象),或者通过强制完整集合来演示这一点。
强制收集不是
真正的解决方案,但会证明这不是问题,当进程需要空闲内存时它们将被释放,然后垃圾收集器将进行完整收集。希望可以帮助到有需要的人
Control.Dispose();
这是一个基本的方法,但对我来说确实有效。首先,
this.InitializeComponent();
现在我能够获得的解决方案是实现一个void函数,其中控件的加载就像表单的设计一样(我从设计代码中的Control中获取了所有信息并将其放入一个void函数中)所以如下(示例是textBox):
private void newControl(){
control.Dispose()之后的方法中的实现是这样的:
this.textBox1 = new System.Windows.Forms.TextBox();;
this.SuspendLayout();
// // 文本框1 //
this.textBox1.Location = new System.Drawing.Point(X, Y);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(Length, Width);
this.textBox1.TabIndex = int;
this.textBox1.Click += new System.EventHandler(this.textBox1_Click);
this.Controls.Add(this.textBox1);
this.PerformLayout();
}
private void button1_Click(object sender, EventArgs e){
textBox1.Dispose();
newControl();
}