在加载Winform窗体的时候,有时候我们在窗体里边会有很多复杂的子窗体,特别是由treeView的时候,我们每次切换treeView都需要加载新的窗体,为了更好的用户体验,我们通常在第一次加载窗体的时候就把所有的界面加载完毕,以后切换treeView的时候只需要把需要的窗体bringtofront就可以了,但是过多的窗体加载会使我们第一次加载窗体的时候出现卡顿,这个时候我们就需要使用异步加载。下面使用一个例子来说明:
这个界面的左侧是12个树节点,当然在右侧会对应12个不同的界面,如果我们按顺序加载,代码应该如下:
public partial class FormLoadTest : Form { private Dictionary<String, UserControl> dicForms = new Dictionary<String, UserControl>(); public FormLoadTest() { InitializeComponent(); } private void FormLoadTest_Load(object sender, EventArgs e) { AddControls(); PanelAddControl(); treeView1.SelectedNode = treeView1.Nodes[0]; } private void AddControls() { string formNames = "UserControl1;UserControl2;UserControl3;UserControl4;UserControl5;UserControl6;UserControl7;UserControl8;UserControl9;UserControl10;UserControl11;UserControl12"; string[] forms = formNames.Split(';'); UserControl control; foreach (string form in forms) { switch (form) { case "UserControl1": control = new UserControl1(); break; case "UserControl2": control = new UserControl2(); break; case "UserControl3": control = new UserControl3(); break; case "UserControl4": control = new UserControl4(); break; case "UserControl5": control = new UserControl5(); break; case "UserControl6": control = new UserControl6(); break; case "UserControl7": control = new UserControl7(); break; case "UserControl8": control = new UserControl8(); break; case "UserControl9": control = new UserControl9(); break; case "UserControl10": control = new UserControl10(); break; case "UserControl11": control = new UserControl11(); break; case "UserControl12": control = new UserControl12(); break; default: control = new UserControl(); break; } if (!dicForms.ContainsKey(form)) { control.Dock = DockStyle.Fill; dicForms.Add(form, control); } } } private void PanelAddControl() { foreach (KeyValuePair<string, UserControl> pair in dicForms) { if (!splitContainer1.Panel2.Controls.Contains(pair.Value)) { splitContainer1.Panel2.Controls.Add(pair.Value); } } } private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { dicForms[treeView1.SelectedNode.Name].BringToFront(); }
为了更明显的表示问题所在,我们在给个子界面初始化的时候都阻塞了300毫秒。这样,实际加载的时候会加载的很慢,这是我们可以想到,既然界面第一次展示的是树节点的第一个结点,我们只需要加载一个界面就可以了,其他的界面另起一个线程去加载,所以我们在Form_Load的时候只需要调用
private void AddFirstForm() { UserControl control = new UserControl1(); control.Dock = DockStyle.Fill; dicForms.Add("UserControl1", control); PanelAddControl(); treeView1.SelectedNode = treeView1.Nodes[0]; } private void FormLoad_Load(object sender, EventArgs e) { AddFirstForm(); Thread thread = new Thread(AddFormsAysnc); thread.Start(); treeView1.Enabled = false; }
Load里边其他的代码就是去异步加载其他的界面,AddFormsAysnc方法如下:
private void AddFormsAysnc() { Thread.Sleep(100); MethodInvoker invoke = new MethodInvoker(AddOtherForms); BeginInvoke(invoke); } private void AddOtherForms() { AddControls(); PanelAddControl(); treeView1.Enabled = true; }
图中标记的是重点,说是异步加载,其实真正初始化界面的时候还是在主线程进行的,所以我们可以
Thread.Sleep(100);保证加载其他界面的时候主界面已经出来了
源代码链接地址 https://files.cnblogs.com/files/sauronKing/FormLoadTest.rar