文章目录
如果要解决“C#winform 点叉叉按钮关闭一form窗体应用后,后台进程仍在运行”的问题,可以直接点击目录跳转到3.4关闭窗体的多种方法。
前面为记录遇到该问题的一些过程。
之前用C#做了一个日志备份的窗体应用程序,最近把这个程序完善了一下,在窗体上显示了配置文件中的一些信息,并且增加了更新按钮,点击会将一些比较重要的配置写到日志文件中。

但是在测试的时候发现了一个问题,运行生成的Release文件中的exe文件(因为最后要放到服务器上使用,不会将整个项目拷贝过去,只拷贝Release文件)。

在第一次运行的时候没什么问题,但是将程序关闭后,修改完配置文件中的线程数再启动的时候,窗体可以正常显示,备份功能也可以正常实现,但是日志中没有写入任何东西,点击更新按钮也没有将配置文件中的信息写入日志当中。下面的是第一次运行的时候写入的,但是后面就不显示了,点击更新按钮也不显示。

因为程序里面有使用多线程,我想会不会是在vs上运行程序生成项目的时候,线程数被固定了,后续更改配置文件的线程数与生成时项目中的线程数不一致导致程序出错。

首先生成了一个4线程的项目,然后运行Release文件中的exe文件,发现功能没问题,日志也可以写入。
然后将窗体关闭,将配置文件中的线程数改为3,窗体启动后发现无法正常使用。
然后将窗体关闭,将配置文件中的线程数改为2,亦是如此。
然后将窗体关闭,将配置文件中的线程数改回4,亦是如此。
后续又做了如下验证:

期间有debug,开启线程没有问题,会按照配置文件中修改的参数来开启对应的线程,点击按钮也有执行日志写入功能,只是.log日志文件中没有实际写入,这说明程序应该是没有问题的。
根据上面的验证结果,得出的结论是跟生成的线程数没有关系。
我想起之前在更新版本的时候,需要删除之前的版本或者给之前版本的文件加上日期,在应用窗体已经关闭的情况下还是显示该文件被占用无法删除或者修改,打开任务管理器,会发现有好几个该程序的进程正在运行,如实想会不会是因为该程序在上次关闭的时候没有彻底关闭,后来又运行exe的时候导致开了好几个,导致日志无法写入。
运行Release文件中的exe文件,将窗体应用关闭后,发现后台进行并没有关闭

此时不做任何修改,再执行exe文件,窗体启动后发现无法正常使用。
然后手动在任务管理器中结束该进程,重新启动exe,发现功能可以正常使用。
修改配置文件中的线程数,重新启动exe,发现功能可以正常使用。
功能无法正常使用就是因为程序进行没有完全结束,即使关闭了窗体应用,但是程序还在后台运行,如果在每次启动前去任务管理器将该进程关闭,该就可以解决。
但是该方法比较麻烦,而且治标不治本,于是便开始查询为什么会出现这种情况。
有的说是有许多人在用做c# 做登录窗体时,登录成功后当前登录Form关闭,打开Main窗体,但Main窗体点关闭按钮后程序仍在进程仍旧在运行。
事实上,关闭Main窗体,只是关闭了Main窗体的线程,并没有关闭程序的主线程,即程序的主线程为登录From。
但是我这个只有一个窗口,所以不存在多窗体没有关闭的情况。
我的真实情况是程序里面开线程了,有托管线程(非主线程),无法干净地退出。
有的说在FormClosing中添加Application.Exit()可以彻底结束进程。
怎么使用FormClosing事件,可以参考:
链接: FormClosing事件在哪,怎么打开FormClosing事件
于是添加了如下代码:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("将要关闭窗口,是否继续?", "询问", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = false;
Application.Exit();
}
else
{
e.Cancel = true;
}
}
但是发现关闭窗体后程序依旧没有彻底关闭。
当我们关闭窗口时,只是停止了当前窗口的消息循环。当Main函数中有消息循环的窗口,这个消息循环结束后,Main函数就基本上完成了历史使命,整个应用程序自然就结束了。
而Application.Exit()方法是终止所有线程上的消息循环,一般情况下,无论在什么地方调用此方法,程序就能退出。
但是如果你在程序中加入了某些耗时甚至是死循环的线程,那么即使是消息循环终止,程序也依然不会结束。
而且这个代码还有一个问题,会导致显示确定退出的两次对话框,第一次单击“确定”第二次单击任何一个都会退出。
因为第一次单击了退出对话框的“确定”按钮后,Application.Exit();会导致触发第二次FrmMain_FormClosing()事件,所以就会显示两个确认退出的对话框,但第二对话框的选择对是否退出没有影响。可以改为判断如果单击了不是确认按钮则e.Cancel = true; ,确定按钮什么都不写或不做判断,如果要加上Application.Exit(); 可以将其添加到窗体的FormClosed事件中。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("将要关闭窗口,是否继续?", "询问", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
//20221227 窗体关闭
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
这样就不会出现弹出两次窗口的情况,但是程序没有彻底结束的问题依旧没有解决。
在Form1_FormClosed事件中加入强制结束进程并退出。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("将要关闭窗口,是否继续?", "询问", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
//20221227 窗体关闭
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
//强制结束进程并退出
//System.Diagnostics.Process.GetCurrentProcess().Kill();
System.Environment.Exit(0);
}
在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.ExitThread(); System.Environment.Exit(0); 等他们各自又有一些不一样的地方,下面详细介绍一下。
1.this.Close(); 只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出;
2.Application.Exit(); 强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出;
3.Application.ExitThread(); 强制中止调用线程上的所有消息,同样面临其它线程无法正确退出的问题;
4.System.Environment.Exit(0); 这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。
这里来说一下FormClosing事件和FormClosed事件
FormClosing事件
在窗体关闭时,FormClosing事件发生。此事件会得到处理。从而释放与窗体相关的所有资源。
如果取消此事件,则窗体仍然保持打开状态。
当窗体显示为模式对话框时,单击“关闭”会隐藏窗体并将DialogResult属性设为Cancel。
通过在些事件中设置DialogResult属性可以在用户单击右上角关闭按钮时重写DialogResult的值。
FormClosed事件
在用户或Application类的Close方法或Exit方法关闭窗体后,会发生FormClosed事件。
可以使用此事件释放窗体的一些资源。还可以使用此事件保存输入窗体中的一些信息或者更新父窗体。
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11
我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在