关闭窗体后,进程仍然在运行的问题重现与解决
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是不管線程有沒有工作都強制關閉所有線程進而正常結束進程。
我們這里不去探討哪種方法更好,只想對解決此類問題的思考方向給出一個說明,那就是:通過結束所有線程的工作來保證進程的正常結束。當然這也是本文的一個主題。
好了,就寫到這里了,希望沒有離題。
---------------------
總結
以上是生活随笔為你收集整理的关闭窗体后,进程仍然在运行的问题重现与解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4.9利率上浮25%是多少
- 下一篇: 首付付了贷款下不来怎么办