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

用到的方法很简单,就是程序运行就建立一个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很多的窗体实例了。

[C#]窗体切换--避免开启多个线程的更多相关文章

  1. python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池

    0.承上 什么是线程? CPU调度的最小单位. 线程是进程的必要组成单位. 主线程: 程序开始运行的时候,就产生了一个主线进程来运行这个程序. 子线程: 是由主线程开启的其他线程. · 各线程之间的工 ...

  2. 并发编程---线程---开启方式---进程线程的区别----Thread的其他属性

    线程 进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合)而线程才是cpu上的执行单位 1.同一个进程内的多个线程共享该进程内的地址资源 2.创建线程的开销远小于创建进程的开销(创建一 ...

  3. 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  4. mui 窗体切换

    手机实现窗体切换 1.在5+环境下(即H5app) 先初始化: mui.init({ subpages:[{ url:"page1.html",//子页面HTML地址,支持本地地址 ...

  5. 很实用的HTML5+CSS3注册登录窗体切换效果

    1. [代码]3个很实用的HTML5+CSS3注册登录窗体切换效果 <!DOCTYPE html><!--[if lt IE 7 ]> <html lang=" ...

  6. CyclicBarrier开启多个线程进行计算,最后统计计算结果

    有一个大小为50000的数组,要求开启5个线程分别计算10000个元素的和,然后累加得到总和 /** * 开启5个线程进行计算,最后所有的线程都计算完了再统计计算结果 */ public class ...

  7. phaser,开启三个线程分别搜索三个文件夹

    Phaser表示“阶段器”,用来解决控制多个线程分阶段共同完成任务的情景问题 启动三个线程,分别对三个文件夹搜索,文件要以txt结尾,修改时间要在一天之内,并将文件路径打印在控制台 /** * 开启三 ...

  8. 开启两个线程,一个线程打印A~Z,一个线程打印1~52的数据

    开启两个线程,一个线程打印A-Z,一个线程打印1-52的数据 import java.util.concurrent.locks.Condition; import java.util.concurr ...

  9. c# winform中窗体切换后释放及防止重复生成

    问题1:窗体切换后如何关闭,并释放资? c# winform中,2个窗体,form1和form2,互相切换的时候执行 this.Hide(); Form2 form2 = new Form2(); f ...

随机推荐

  1. 常用CSS HACK

    常用CSS HACK IE6 3像素bug和双边距bug一样的经典 现象: IE6下浮动元素和不浮动元素之间会有3px间隙(3px bug,div.float-left + div.float-non ...

  2. 派生类地址比基类地址少4(子类与基类指针强行转换的时候,值居然会发生变化,不知道Delphi BCB是不是也这样) good

    大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸.我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree ...

  3. Mirantis Certification summary

    preface Mirantis Certification (MCA100 )summary roughly question types handy remain by Ruiy!

  4. [置顶] js模板方法的思路及实现

    在js中如何实现设计模式中的模板方法? 思路的产生必然要求熟悉js,如何实现?就很简单了,都知道在js中如果定义两个相同名称的方法,前一个方法就会被后一个方法覆盖掉,使用此特点就可以实现模板方法. 例 ...

  5. java之Set源代码浅析

    Set的接口和实现类是最简单的,说它简单原因是由于它的实现都是基于实际的map实现的. 如 hashSet 基于hashMap,TreeSet 基于TreeMap,CopyOnWriteArraySe ...

  6. bmob云 实现注册和登录的功能

    向大家介绍一款我感觉非常溜的一款后端云服务bmob云 借助bmob云我们可以实现注册和登录页面的功能,下面就让我给大家演示一下借助bmob云服务实现这两个功能吧.  1. 用户是一个应用程序的核心.对 ...

  7. 谈如何使用c中的qsort快速排序库函数 按主次关键字正确排序

    快排的效率很快,但是我们很少知道如何利用它进行多关键字排序,比如我想对一个数组a[i][0]进行的一个元素进行主关键字排序,又想对a[i][1]进行次关键字排序.那么接下来就是解决这个问题的方法. 学 ...

  8. 不直接用NSLog

    公司中不直接使用NSLog,而是利用宏定义自己的打印函数,将该打印函数写在项目的.pch文件中.调试的时候往往用到好多打印,但发布的时候确不需要.(一下是在公司中的一些处理) 自定义NSLog 一,固 ...

  9. 关于$.ajax的请求格式

    1 $.ajax({ 2 url: "http://localhost:5311/UserService.asmx/GetLoginId",//请求的URL 3 type: &qu ...

  10. bzoj 1057: [ZJOI2007]棋盘制作 单调栈

    题目链接 1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2027  Solved: 1019[Submit] ...