I have a project which after some time can have thousands of controls on it, and each of those controls are being disposed cleanly, however this process is starting to take up a lot of processor time and it locks the UI when calling Dispose on the parent object.
Is there anyway to do a cascade dispose of all objects and sub objects inside a container without blocking the UI in the process ?
To replicate the problem, you can create a new Control, with a sub Control, and each of those sub controls, add another control to them. After this, make sure you have proper Dispose() code in each control and sub control, then use this loop in the parent Dispose() method:
while(Controls.Count > 0) { Controls[0].Dispose(); }
Then drop this new control with multiple sub controls (I use a custom Add method to add all the sub controls to the parent).
Once you have a hundred or so of these controls visible in the new control container, call it's dispose method --- the absolute parent of your custom control. A simple structure would be as follows (not including their sub Dispose methods)
public class MyCoolClass : ScrollableContainer, IDisposable {
public List<MyBox> Boxes { get; set; }
public MyCoolClass() {
Boxes = new List<MyBox>();
}
public Add() {
MyBox box = new MyBox();
int next_top = 0;
if(Boxes.Count > 0) {
next_top = Boxes[Boxes.Count-1].Top + Boxes[Boxes.Count-1].Height + 10;
} else {
next_top = 10;
}
box.Top = next_top;
Boxes.Add(box);
Controls.Add(box);
}
public ReloadBoxes() {
Controls.Clear();
SuspendUpdate();
int next_top = 0;
foreach(MyBox box in Boxes) {
if(next_top==0) { next_top = 10; }
box.Top = next_top;
next_top = box.Top + box.Height + 10;
}
ResumeUpdate();
}
internal class MyBox : Control, IDisposable {
internal class WriteArea : RichTextBox, IDisposable {
}
WriteArea TT;
public MyBox() {
TT = new WriteArea();
}
}
}
Copy the controls to a separate collection, clear the controls from the form and then spin off a background worker to handle the dispose.
Backgroundworker