1 问题陈述

在开发中,遇到这样一个问题:

点击程序主窗体右上角的叉号关闭应用程序后,程序的进程却没有关闭。

通过查阅资料,了解到,产生此类问题的原因主要有以下两点:

1)程序中存在死循环。

2)程序为多线程程序,且在窗体关闭后,仍有线程在工作。

本文将针对此类问题,进行重现并提出解决方案。

2 场景再现

@场景1

新建Windows应用程序CloseWindowExp,程序每隔一秒钟改变一次窗体的背景色。

程序运行后的效果,如下图所示(变化的过程,就请大家在脑子中想象一下吧)。

程序的主要代码如下所示。

//************************************************************
//
// 窗体关闭问题示例代码
//
// Author:三五月儿
//
// Date:2014/07/27
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace CloseWindowExp
{
public partial class frmCase1 : Form
{
Random rand = new Random();
public frmCase1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
int c1 = rand.Next(0, 244);
int c2 = rand.Next(0, 244);
int c3 = rand.Next(0, 244);
this.BackColor = Color.FromArgb(c1,c2,c3);
Application.DoEvents();
Thread.Sleep(1000);
}
}
}
}
代码中,通过While循环来实现每隔一秒钟改变一次窗体背景色的工作,每一次循环中,会随机生成三个整数c1、c2、c3,并使用这三个整数来生成窗体的背景色,紧接着,执行Application.DoEvents()方法,使用此方法可以确保即使在循环中窗体也有反映(要不,你去掉再看看会有什么效果),每次循环的最后会让程序Sleep一小会(1s钟),这样就可以使颜色变化的间隔近似保持在1s钟左右。
运行程序再点击窗体右上角的叉号关闭窗体(是关闭窗体哦,其实以前我一直都认为,关闭了窗体也就关闭了程序,现在看来,这是不正确的),再打开任务管理器,打开“进程”项,在列表中寻找CloseWindowExp的身影,很不幸,找到了,请看下图。

@场景二

场景二所给示例,完成场景一示例一样的工作,只是将工作转移至一个新的工作线程中。

下面是场景二示例的主要代码。

//************************************************************
//
// 窗体关闭问题示例代码
//
// Author:三五月儿
//
// Date:2014/07/27
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace CloseWindowExp1
{
public partial class frmCase2 : Form
{
Random rand = new Random();
public frmCase2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(()=>
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() =>
{
while (true)
{
int c1 = rand.Next(0, 244);
int c2 = rand.Next(0, 244);
int c3 = rand.Next(0, 244);
this.BackColor = Color.FromArgb(c1, c2, c3);
Application.DoEvents();
Thread.Sleep(1000);
}
}));
}
});
t.Start();
}
}
}
其实,对于这里场景二所给的的示例,我是有一点不放心的,生怕使用它不能很好地说明我想要表达的内容,因为本质上他跟示例一没有任何差别,都是因为在程序中存在一个死循环才导致了问题的发生。

在研究这类问题发生的原因时,我们完全可以这样去考虑,当窗体被关闭后,程序为什么还在运行呢,肯定是因为程序还有没干完的工作,当然这件工作有可能再过一会就干完了,也有可能永远也干不完(死循环),至于这工作是谁干的,是主线程,还是工作线程,本质上没有区别。通过我们所给的两个实例,正好说明这点,因为实例一的工作是在主线程中完成的,而实例二的工作是在工作线程中完成的。但是,不管是主线程,还是工作线程,只要存在未完成的工作都会导致此类问题的发生。所以,此类问题的原因,最终可以归结为一点:关闭窗体时,只要有线程还在工作,进程都不会被结束。

在实际开发中,我们经常会使用一个工作线程去干一些重复的工作,所以,在多线程开发中,更容易出现死循环或者关闭了窗体还需要工作一段时间的场景。因此,多线程开发中更要注意此类问题的发生。

找到了原因,解决问题就简单了。对于此类问题的解决,只要确保在窗体关闭后没有任何线程在工作即可。至于具体解决方案可以视情况而定。

3 解决方法

@方法1

将循环条件while (true)修改为while (this.Visible)。

这样一来,当窗体关闭后,窗体的Visible属性值变为false,则while循环随即被终止,进而进程也会被正常结束。

@方法2

在窗体的FormClosing事件处理方法中,使用代码System.Environment.Exit(0)强制退出当前进程,这样一来,不管进程下是否还有线程在工作,都会一概结束。

private void frmCase2_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(0);
}
方法1的原理是结束程序中的死循环进而结束线程,从而使进程能够正常结束;而方法2是不管线程有没有工作都强制关闭所有线程进而正常结束进程。
我们这里不去探讨哪种方法更好,只想对解决此类问题的思考方向给出一个说明,那就是:通过结束所有线程的工作来保证进程的正常结束。当然这也是本文的一个主题。

好了,就写到这里了,希望没有离题。
---------------------

关闭窗体后,进程仍然在运行的问题重现与解决相关推荐

  1. 关于C#关闭窗体后,依旧有后台进程在运行的解决方法

    关于C#关闭窗体后,依旧有后台进程在运行的解决方法 参考文章: (1)关于C#关闭窗体后,依旧有后台进程在运行的解决方法 (2)https://www.cnblogs.com/leo-navy/p/8 ...

  2. eclipse修改代码后,重新部署运行还是上次的结果——解决方法

    目录 目录 前言 找出问题 如何解决 情况一:控制台未报错--找到sql语句,查看sql语句是否为最新修改的sql 情况二:控制台报错 前言 在项目上偶然遇到一个问题:在使用mybatis开发时,新修 ...

  3. 关机提示 ”task host window任务宿主正在执行关闭任务并且正在停止已运行的任务“我是这样解决的

    最近电脑在关机时,总会出现这个提示,需要你强制关机 可以这么处理一下: win+R 召唤"运行"对话窗口,输入regedit 召唤注册表编辑器在如下路径计算机\HKEY_LOCAL ...

  4. 计算机无法关闭怎么办,电脑进程无法关闭怎么办

    有时候我们会遇到这种情况,就是任务管理器无法结束进程,那么电脑进程无法关闭怎么办呢?接下来大家跟着学习啦小编一起来了解一下电脑进程无法关闭的解决方法吧. 电脑进程无法关闭解决方法 一.普通进程--Ta ...

  5. Idea(11):强制关闭Tomcat后,重启tomcat提示端口8080被占用

    问题: Idea强制关闭Tomcat后,重启tomcat提示端口8080被占用 解决方法: CMD进入命令窗口 $netstat -aon|findstr 8080 $taskkill -f -pid ...

  6. 如果在BackgroundWorker运行过程中关闭窗体…

    在Windows Form应用中,BackgroundWorker 类允许您在单独的专用线程上运行操作.耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态 ...

  7. XenApp For Windows 2016 关闭程序后无法结束进程

    XenDesktop7.15 LSTR CU1 VDA:Windows 2016 场景:通过XenApp方式打开一个已发布的应用程序,关闭应用程序后会话没有结束,在服务器上继续驻留,除了继续占用服务器 ...

  8. LINUX远程连接关闭后进程退出的解决方案

    由于项目需要,开发的程序需要在LINUX上运行,后来发现一个问题,当我在窗口执行命令java xxxxxxxx之后,关掉窗口那么进程也就自动关闭了,后来去网上找了一些资料,有几个简单的方法,也看到了基 ...

  9. 使用Screen使SSH关闭后Meteor服务继续运行

    2019独角兽企业重金招聘Python工程师标准>>> 本文基于Ubuntu 14.04 使用SSH连接远程服务器,启动服务,退出SSH后,服务也就终止了,使用Screen可以解决这 ...

最新文章

  1. CF961G-Partitions【斯特林数】
  2. HI3798MV200驱动移植
  3. 使用pip无法完全卸载autoitlibrary,提示 we cannot accurately determine which files belong to it which would‘解决办法
  4. 研究生可以不用学英语?只要考研英语或六级分数高!
  5. STM8S003串口printf及帧判断
  6. vsftp中anon_world_readable_only参数具体使用
  7. linux rm、rm -f、rm -r的区别
  8. 重装系统进入PE的快捷键大全
  9. Win10 英伟达显卡驱动安装不上,显示由于该设备有问题,Windows已将其停止,错误代码43
  10. JS数组、字符串、数字的相互转化
  11. 那些在一个公司死磕了5-10年的人,最后都怎么样了?那些在一个公司死磕了5-10年的人,最后都怎么样了?...
  12. ES 与关系型数据库的对比
  13. 《云计算技术与应用》最新章节测试答案
  14. https://www.cnblogs.com/richered/p/8344087.html
  15. SQL 之 模糊匹配
  16. ggplot2-数据分布型图表
  17. uni-ui使用方式
  18. ADAMS的二连杆机械臂PID控制
  19. spring-cloud版本与兼容
  20. 阿里巴巴ICBU技术部22届实习招聘

热门文章

  1. Qt Creator在外部应用程序上运行Valgrind工具
  2. OpenGL键盘消息实例
  3. OpenGL CPU射线行进
  4. 经典C语言程序100例之八七
  5. parzen窗估计如何进行结果分析_实现一下模式识别(一)Parzen窗估计
  6. java只有值传递_面试官:为什么 Java 中只有值传递?
  7. 01_Win10下CUDA的安装、查看并升级Nvidia显卡驱动、安装CUDA、设置环境变量、测试CUDA是否安装成功
  8. 07_clickhouse、自定义分区及底层存储合并机制、自定义分区键、分区目录的命名规则、分区目录的合并过程、分区目录的合并过程、分区表达式指定、分区案例
  9. B04_NumPy从已有的数组创建数组(numpy.asarray,numpy.frombuffer,numpy.fromiter)
  10. 4.Maven概念模型,maven的生命周期,Maven坐标,依赖管理(依赖范围,依赖声明),仓库管理,私服概念