[C#]窗体切换--避免开启多个线程

先说说这个多窗体的界面的解决的办法:

用到的方法很简单,就是程序运行就建立一个MainForm,在这个MainForm中设立一个Panel,同时设立几个按钮,按下每个按钮都在这个Panel中载入不同的窗体,这样就解决了多窗体的切换。

 提示:

在Panel的子窗体可以通过设置Form的FormBorderStyle为none,去掉它的最大化最小化和关闭按钮。但是一旦设置这个属性就必须手动的调用这个窗体的close方法来关闭这个窗体,因为调用这个方法和鼠标点击窗体的x按钮是一样的效果,都会调用窗体的close函数。同时这个函数的调用也会触发窗体的formclosing等事件。

下面看一下第一次写的代码:

//MainForm的代码
public class RobotArrounding : Form
{
	private int curSelect = 0;

	public RobotArrounding()
	{
		InitializeComponent();


		this.pnlMain.Controls.Clear();
		MonitorForm monitorFrm = new MonitorForm();

		monitorFrm.TopLevel = false;
		monitorFrm.Dock = DockStyle.Fill;
		monitorFrm.Show();

		this.pnlMain.Controls.Add(monitorFrm);

	}

	private void btnMonitor_Click(object sender, EventArgs e)
	{
		if (curSelect != 0)
		{
			this.pnlMain.Controls.Clear();
			MonitorForm monitorFrm = new MonitorForm();

			monitorFrm.TopLevel = false;
			monitorFrm.Dock = DockStyle.Fill;
			monitorFrm.Show();

			this.pnlMain.Controls.Add(monitorFrm);
		}

		curSelect = 0;

	}

	private void btnPlane_Click(object sender, EventArgs e)
	{
		if (curSelect != 1)
		{
			this.pnlMain.Controls.Clear();

			CheckingPlane planeFrm = new CheckingPlane();

			planeFrm.TopLevel = false;
			planeFrm.Dock = DockStyle.Fill;
			planeFrm.Show();

			this.pnlMain.Controls.Add(planeFrm);
		}
		curSelect = 1;
	}

	private void btnHistoryChecking_Click(object sender, EventArgs e)
	{
		if (curSelect != 2)
		{
			this.pnlMain.Controls.Clear();
			HistoryChecking historyFrm = new HistoryChecking();

			historyFrm.TopLevel = false;
			historyFrm.Dock = DockStyle.Fill;
			historyFrm.Show();

			this.pnlMain.Controls.Add(historyFrm);
		}
		curSelect = 2;
	}

	private void bntExit_Click(object sender, EventArgs e)
	{
		this.Close();
		//退出整个程序
		Application.Exit();
	}
}

  代码很简单,每次点击按钮都new一个新的窗体并显示。但是后来发现这样有问题,那就是多次按按钮,切换界面以后,原本new出来的窗体并没有销毁,没有被垃圾回收器收回。而是在整个程序退出的时候才调用了窗体的close方法,验证的方法就是在每一个窗体中增加formclosing事件,验证这个事件触发的时间,代码:

//其中的一个界面的类
public partial class CheckingPlane : Form
{
	public CheckingPlane()
	{
		InitializeComponent();
	}

	private void CheckingPlane_FormClosing(object sender, FormClosingEventArgs e)
	{
		int a = 0;
		a = 10;
	}
}

  在MainForm调用application.Exit()方法得时候,发现这个窗体类的FormClosing事件执行了好多次,这个原因就是切换好多次的窗体之后,new出来了好多的窗体的实例。

解决的办法:

如果一个窗体没有被要求显示,那么这个窗体就不用new一个实例,如果这个窗体要求显示,那么就new一个窗体的实例,然后一直保持一个窗体的单例模式,直到整个程序退出时才销毁这个窗体。

public partial class RobotArrounding : Form
{
	private int curSelect = 0;
	private Form[] selectFrm = null;

	public RobotArrounding()
	{
		InitializeComponent();
		selectFrm = new Form[3];

		this.pnlMain.Controls.Clear();

		selectFrm[0] = new MonitorForm();

		selectFrm[0].TopLevel = false;
		selectFrm[0].Dock = DockStyle.Fill;
		selectFrm[0].Show();

		this.pnlMain.Controls.Add(selectFrm[0]);

	}

	private void btnMonitor_Click(object sender, EventArgs e)
	{
		if (curSelect != 0)
		{
			this.pnlMain.Controls.Clear();
			if (selectFrm[0] == null || selectFrm[0].IsDisposed)
			{
				selectFrm[0] = new MonitorForm();

				selectFrm[0].TopLevel = false;
				selectFrm[0].Dock = DockStyle.Fill;
				
			}
			else 
			{
				selectFrm[0].Activate();
			}

			selectFrm[curSelect].Hide();
			selectFrm[0].Show();


			this.pnlMain.Controls.Add(selectFrm[0]);
		}
		curSelect = 0;

	}

	private void btnPlane_Click(object sender, EventArgs e)
	{
		if (curSelect != 1)
		{
			this.pnlMain.Controls.Clear();

			if (selectFrm[1] == null || selectFrm[1].IsDisposed)
			{
				selectFrm[1] = new CheckingPlane();

				selectFrm[1].TopLevel = false;
				selectFrm[1].Dock = DockStyle.Fill;
			}
			else
			{
				selectFrm[1].Activate();
			}

			selectFrm[curSelect].Hide();
			selectFrm[1].Show();

			this.pnlMain.Controls.Add(selectFrm[1]);
		}
		curSelect = 1;
	}

	private void btnHistoryChecking_Click(object sender, EventArgs e)
	{
		if (curSelect != 2)
		{
			this.pnlMain.Controls.Clear();

			if (selectFrm[2] == null || selectFrm[2].IsDisposed)
			{
				selectFrm[2] = new HistoryChecking();

				selectFrm[2].TopLevel = false;
				selectFrm[2].Dock = DockStyle.Fill;
			}
			else
			{
				selectFrm[2].Activate();
			}

			selectFrm[curSelect].Hide();
			selectFrm[2].Show();

			this.pnlMain.Controls.Add(selectFrm[2]);
		}
		curSelect = 2;
	}

	private void bntExit_Click(object sender, EventArgs e)
	{
		for (int i = 0; i < 3; i++ )
		{
			if (selectFrm[i] != null)
			{
				selectFrm[i].Close();
			}
		}

		this.Close();

		Application.Exit();
	}

}

  这样写还有一个小的问题,那就是我自己的继承自Form的窗体类,如果有自己定义的函数,利用多态访问这个窗体的时候就不能访问到这个函数。其实这个也很简单,在需要访问子类自定义的函数的时候,强制转换一下类型就可以了。

 这样一来,不管你切换多少次窗体,都只有一个窗体的实例了,这样就能防止new很多的窗体实例了。

原文地址:https://www.cnblogs.com/stemon/p/4557504.html