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

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

提示:

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

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

  1. //MainForm的代码
  2. public class RobotArrounding : Form
  3. {
  4. private int curSelect = 0;
  5.  
  6. public RobotArrounding()
  7. {
  8. InitializeComponent();
  9.  
  10. this.pnlMain.Controls.Clear();
  11. MonitorForm monitorFrm = new MonitorForm();
  12.  
  13. monitorFrm.TopLevel = false;
  14. monitorFrm.Dock = DockStyle.Fill;
  15. monitorFrm.Show();
  16.  
  17. this.pnlMain.Controls.Add(monitorFrm);
  18.  
  19. }
  20.  
  21. private void btnMonitor_Click(object sender, EventArgs e)
  22. {
  23. if (curSelect != 0)
  24. {
  25. this.pnlMain.Controls.Clear();
  26. MonitorForm monitorFrm = new MonitorForm();
  27.  
  28. monitorFrm.TopLevel = false;
  29. monitorFrm.Dock = DockStyle.Fill;
  30. monitorFrm.Show();
  31.  
  32. this.pnlMain.Controls.Add(monitorFrm);
  33. }
  34.  
  35. curSelect = 0;
  36.  
  37. }
  38.  
  39. private void btnPlane_Click(object sender, EventArgs e)
  40. {
  41. if (curSelect != 1)
  42. {
  43. this.pnlMain.Controls.Clear();
  44.  
  45. CheckingPlane planeFrm = new CheckingPlane();
  46.  
  47. planeFrm.TopLevel = false;
  48. planeFrm.Dock = DockStyle.Fill;
  49. planeFrm.Show();
  50.  
  51. this.pnlMain.Controls.Add(planeFrm);
  52. }
  53. curSelect = 1;
  54. }
  55.  
  56. private void btnHistoryChecking_Click(object sender, EventArgs e)
  57. {
  58. if (curSelect != 2)
  59. {
  60. this.pnlMain.Controls.Clear();
  61. HistoryChecking historyFrm = new HistoryChecking();
  62.  
  63. historyFrm.TopLevel = false;
  64. historyFrm.Dock = DockStyle.Fill;
  65. historyFrm.Show();
  66.  
  67. this.pnlMain.Controls.Add(historyFrm);
  68. }
  69. curSelect = 2;
  70. }
  71.  
  72. private void bntExit_Click(object sender, EventArgs e)
  73. {
  74. this.Close();
  75. //退出整个程序
  76. Application.Exit();
  77. }
  78. }

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

  1. //其中的一个界面的类
  2. public partial class CheckingPlane : Form
  3. {
  4. public CheckingPlane()
  5. {
  6. InitializeComponent();
  7. }
  8.  
  9. private void CheckingPlane_FormClosing(object sender, FormClosingEventArgs e)
  10. {
  11. int a = 0;
  12. a = 10;
  13. }
  14. }

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

解决的办法:

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

  1. public partial class RobotArrounding : Form
  2. {
  3. private int curSelect = 0;
  4. private Form[] selectFrm = null;
  5.  
  6. public RobotArrounding()
  7. {
  8. InitializeComponent();
  9. selectFrm = new Form[3];
  10.  
  11. this.pnlMain.Controls.Clear();
  12.  
  13. selectFrm[0] = new MonitorForm();
  14.  
  15. selectFrm[0].TopLevel = false;
  16. selectFrm[0].Dock = DockStyle.Fill;
  17. selectFrm[0].Show();
  18.  
  19. this.pnlMain.Controls.Add(selectFrm[0]);
  20.  
  21. }
  22.  
  23. private void btnMonitor_Click(object sender, EventArgs e)
  24. {
  25. if (curSelect != 0)
  26. {
  27. this.pnlMain.Controls.Clear();
  28. if (selectFrm[0] == null || selectFrm[0].IsDisposed)
  29. {
  30. selectFrm[0] = new MonitorForm();
  31.  
  32. selectFrm[0].TopLevel = false;
  33. selectFrm[0].Dock = DockStyle.Fill;
  34.  
  35. }
  36. else
  37. {
  38. selectFrm[0].Activate();
  39. }
  40.  
  41. selectFrm[curSelect].Hide();
  42. selectFrm[0].Show();
  43.  
  44. this.pnlMain.Controls.Add(selectFrm[0]);
  45. }
  46. curSelect = 0;
  47.  
  48. }
  49.  
  50. private void btnPlane_Click(object sender, EventArgs e)
  51. {
  52. if (curSelect != 1)
  53. {
  54. this.pnlMain.Controls.Clear();
  55.  
  56. if (selectFrm[1] == null || selectFrm[1].IsDisposed)
  57. {
  58. selectFrm[1] = new CheckingPlane();
  59.  
  60. selectFrm[1].TopLevel = false;
  61. selectFrm[1].Dock = DockStyle.Fill;
  62. }
  63. else
  64. {
  65. selectFrm[1].Activate();
  66. }
  67.  
  68. selectFrm[curSelect].Hide();
  69. selectFrm[1].Show();
  70.  
  71. this.pnlMain.Controls.Add(selectFrm[1]);
  72. }
  73. curSelect = 1;
  74. }
  75.  
  76. private void btnHistoryChecking_Click(object sender, EventArgs e)
  77. {
  78. if (curSelect != 2)
  79. {
  80. this.pnlMain.Controls.Clear();
  81.  
  82. if (selectFrm[2] == null || selectFrm[2].IsDisposed)
  83. {
  84. selectFrm[2] = new HistoryChecking();
  85.  
  86. selectFrm[2].TopLevel = false;
  87. selectFrm[2].Dock = DockStyle.Fill;
  88. }
  89. else
  90. {
  91. selectFrm[2].Activate();
  92. }
  93.  
  94. selectFrm[curSelect].Hide();
  95. selectFrm[2].Show();
  96.  
  97. this.pnlMain.Controls.Add(selectFrm[2]);
  98. }
  99. curSelect = 2;
  100. }
  101.  
  102. private void bntExit_Click(object sender, EventArgs e)
  103. {
  104. for (int i = 0; i < 3; i++ )
  105. {
  106. if (selectFrm[i] != null)
  107. {
  108. selectFrm[i].Close();
  109. }
  110. }
  111.  
  112. this.Close();
  113.  
  114. Application.Exit();
  115. }
  116.  
  117. }

  这样写还有一个小的问题,那就是我自己的继承自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. Windows 取得至高无上的权限

    第一步:gpedit.msc 第二步:计算机配置-->windows 设置 -->安全设置 -->安全选项 -->用户账户控制 -->以管理员批准模式运行所有管理员 -- ...

  2. SQL Server 数据类型陷阱

    1. bit 类型:bit(1) 不要以为它只占一个位,事实上它要占一个字节!也就是说当n < 8 时都是这样的! 2. varchar(n)  这里的n不能大于8000,如果想要比8000大你 ...

  3. Python GUI编程各种实现的对比

    Python GUI编程各种实现的对比 从 Python 语言的诞生之日起,就有许多优秀的 GUI 工具集整合到 Python 当中,这些优秀的 GUI 工具集,使得 Python 也可以在图形界面编 ...

  4. HDU 5893 List wants to travel(树链剖分)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5893 [题目大意] 给出一棵树,每条边上都有一个边权,现在有两个操作,操作一要求将x到y路径上所有边 ...

  5. 1396 - Most Distant Point from the Sea

    点击打开链接 题意: 按顺序给出一小岛(多边形)的点 求岛上某点离海最远的距离 解法: 不断的收缩多边形(求半平面交) 直到无限小 二分收缩的距离即可 如图 //大白p263 #include < ...

  6. proguard混淆jar文件

    Proguard是个优秀的java混淆工具,使用示例如下,一个java工程对外接口代码如下(无需混淆) package com.ciaos.open; import com.ciaos.inner.I ...

  7. To the Max(矩阵压缩)

    To the Max Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other) Total Su ...

  8. SRM 585 DIV 1 总结

    题意:给你一棵高度为H的完全二叉树的路,问最少需要多少辆车把这路走完,车子不能返回. 那么最优的方案就是从小到上一层层的走完,就很容易地可以得到一种递推,需要注意的就是dp[0]  = 1 #incl ...

  9. Introduction to Probability (5) Continus random variable

    CONTINUOUS RANDOM VARIABLES AND PDFS  连续的随机变量,顾名思义.就是随机变量的取值范围是连续的值,比如汽车的速度.气温.假设我们要利用这些參数来建模.那么就须要引 ...

  10. [cocos2dx笔记015]关于cocos2dx Button三种状态说明

    经过几天的填坑,最终将现有的项目由cocos2dx 2.2.2移到cocos2dx 3.2,差点放弃3.2了,但在最后一刻,又把坑填平了. cocos2dx 2.x到3.x是一个巨大的变化,能够算是全 ...