如何在处置/删除控件后重新加载控件
所以我想制作一个包含动态控件布局的程序,有点类似于网页。 我有一个特定的按钮,如果您单击它,它应该处理所有当前可见的控件,并使用第二个 InitializeComponent 加载一组完整的新控件。
第二页将包含一个“后退”按钮,该按钮应该处理第二组控件,并再次使用第一个 InitializeComponent 重新加载原始控件,以便我有 2 个不同的可访问“页面”。
然而,每次我通过按钮切换并再次调用InitializeComponent时,VRAM使用量都会稳步增加,可能是因为它并没有真正通过dispose“杀死”所有以前的资源。
所以我想问是否有一种方法可以重新加载已处理的初始化控件,而不必再次初始化它们。
提前致谢。
编辑: 啊,没关系,我明白了。
当更改到第 2 页时,我只是使用 Controls.Remove 命令来删除当前的控件集,而不是 .dispose。 如果我想返回,我现在可以简单地使用 Controls.Add 命令再次查看第一组控件,并且 VRAM 使用量不会增加。
这对于处置来说是不可能的,有人愿意解释一下吗?我是 csharp 的真正初学者,基本上是几天前开始的。
So I want to make a program that includes dynamic control layouts, kind of similar to a web page.
Theres a certain button that I have, if you click on it it is supposed to dispose all the current controls that can be seen and load a complete new set of controls with a second InitializeComponent.
The second page will include a "back" button that is supposed to dispose the second set of controls, and reload the original ones with the first InitializeComponent again so that I kind of have 2 different accesable "pages".
However, each time I switch via the button and call the InitializeComponent again, the VRAM usage will increase steadily probably because it doesnt really "kill" off all previous resources with dispose.
So I wanted to ask if there's a way to reload initialized controls that have been disposed without having to initialize them again.
Thanks in advance.
EDIT:
ahh nevermind, I got it.
instead of .dispose I just use the Controls.Remove command to remove the current set of controls when changing to page 2.
If i want to go back, I can now simple use the Controls.Add command to view the first set of controls again and VRAM usage does not increase.
This was not possible with dispose, anyone care to explain that? Im a REAL beginner in csharp, basically started a few days ago.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上你不应该自己调用 Dispose() 。通常,当您在表单上调用 Close() 等时,框架会为您执行此操作。
显然,如果仍然存在对各个元素的引用,这并不总是会导致相应元素被删除。这就是您的控件在某种程度上仍然存在的原因。
如果您(出于某种原因)需要 Close() 或 Remove() 以及您保留引用的元素,则应该在执行其他操作之前执行 element.IsDispose 检查。如果这是真的,你应该重新创建它,因为该元素已经半死了。请不要使用死灵术:-)
Actually you are not really supposed to call Dispose() yourself. Normally the framework will do that for you when you call Close() on a Form and such.
Apparently this does not always result in the respective element being removed if there are still references to it. This is the reason your controls where still there in a way.
If you (for some reason) need to Close() or Remove() and element for which you keep a reference you should do a element.IsDisposed check before doing anything else. If this is true you should create it anew because the element is half dead already. No necromancy, please :-)
对任何一次性对象调用 Dispose 应该会导致它释放(将引用设置为 null)任何引用的一次性对象,并清理任何直接引用的非托管资源。对于 UI 控件,处置将释放非托管的底层 Win32 GUI 对象。 Dispose 与释放内存以供重用无关,这是在对象未被某些静态或堆栈(本地)引用(间接)引用时由垃圾收集器完成的。如果您保留对最后一页(要返回)的引用,则其
Controls
集合中的控件仍将被引用并保持活动状态。即使它们已从控件集合中删除并且未引用,但由于 UI 控件往往会存在一段时间,因此它们很可能已从第 0 代(频繁收集)转移到第 1 代甚至第 2 代(很少收集)。除非存在内存压力(您的系统没有太多可用内存),否则可能需要很长时间才能收集它们。
您可以通过使用带有 SOS 扩展的 WinDbg 查看特定对象所在的代(甚至列出该代中的所有对象)或通过强制完整收集来演示这一点。
强制收集并不是真正的解决方案,但会证明这不是问题,当进程需要空闲内存时它们将被释放,然后垃圾收集器将进行完整收集。
Calling
Dispose
on any disposable object should cause it to release (set references to null) any referenced disposable objects, and clean up any directly referenced unmanaged resources. In the case of UI controls disposing will free up the unmanaged underlying Win32 GUI objects. Dispose is not about releasing memory for re-use, that's done by the garbage collector when objects are not referenced (indirectly) by some static or stack (local) reference. If you are keeping a reference to the last page (to go back to) then controls in itsControls
collection will still be referenced and keeping them alive.Even if they are removed from the controls collection and otherwise unreferenced, as UI controls tend to be around for a while it is likely that they have moved from generation zero (collected frequently) to generation 1 or even 2 (collected rarely). Unless there is memory pressure (your system doesn't have much free memory) it might be a long time before collecting them.
You can demonstate this by either using WinDbg with SOS extensions to look at what generation specific objects are in (or even list all objects in that generation), or by forcing a full collection.
Forcing a collection is not a real solution, but would demonstrate it is not a problem, they will be freed when the process needs free memory, then the garbage collector will do a full collection.
我希望这可以帮助需要它的人
我所做的是一种反复试验的方法,通过该方法,我能够在执行
Control.Dispose();
函数后重新加载控件。这是一个基本的方法,但对我来说确实很有效。
首先,
this.InitializeComponent();
方法将控件重新加载到窗体中,因此每次使用时,控件都会重新加载到窗体中,使得Control的数量等于1每次使用它时,您都会增加。现在我能够获得的解决方案是实现一个 void 函数,其中控件的加载就像表单的设计一样(我从设计代码中的 Control 中获取了所有信息并将其放入 void 函数中)
I hope this can help someone who needs it
What I did was a trial and error method, with which I was able to reload a Control after doing the
Control.Dispose();
function.It is a rudimentary method but it really worked for me.
First of all, the
this.InitializeComponent();
method reloads the controls to the form, so every time you use it, the controls are reloaded to the form, making the number of Controls equal to the one you had increase every time you use it.Now the solution that I was able to obtain was to implement a void function in which the control is loaded just as the design of the form does (I took all the information from the Control in the design code and put it in a void function)