方案一:
調用線程式控制制方法.啟動:Thread.Start();停止:Thread.Abort();暫停:Thread.Suspend();繼續:Thread.Resume();
private void btn_Start_Click(object sender, EventArgs e) { mThread.Start(); // 開始 }private void btn_Stop_Click(object sender, EventArgs e) { mThread.Abort(); // 終止 }private void btn_Suspend_Click(object sender, EventArgs e) { mThread.Suspend(); // 暫停 }private void btn_Resume_Click(object sender, EventArgs e) { mThread.Resume(); // 繼續}
線程定義為:
mThread = new Thread(() =>{try{for (int j = 0; j < 20; j++) {int vSum = 0;this.textBox1.Text += "--->";for (int i = 0; i < 100000000; i++) {if (i % 2 == 0) { vSum += i; }else{ vSum -= i; } }this.textBox1.Text += string.Format("{0} => vSum = {1}\r\n", DateTime.Now.ToString(), vSum); Thread.Sleep(1000); } }catch (ThreadAbortException ex) { Console.WriteLine("ThreadAbortException:{0}", ex.Message); } });
值得注意的是: 通過 Thread.Abort() 停下來的線程(或自行運行結束的線程),都無法直接通過 Thread.Start() 方法再次啟動,必須重新建立一個線程啟動。
所以,“開始按鈕”事件應為:
private void btn_Start_Click(object sender, EventArgs e) {// 定義線程mThread = new Thread(() => // Lambda 運算式 {try{for (int j = 0; j < 20; j++) {int vSum = 0;this.textBox1.Text += "--->";for (int i = 0; i < 100000000; i++) {if (i % 2 == 0) { vSum += i; }else{ vSum -= i; } }this.textBox1.Text += string.Format("{0} => vSum = {1}\r\n", DateTime.Now.ToString(), vSum); Thread.Sleep(1000); } }catch (ThreadAbortException ex) { Console.WriteLine("ThreadAbortException:{0}", ex.Message); } }); mThread.Start(); // 開始}
此外,對於 Thread.Suspend() 和 Thread.Resume() 方法,微軟已經將其標記為過時:
Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. (Thread.Suspend 已被否決。請使用系統中的其他類線程,如監視器、互斥體、事件和訊號量,以同步線程或保護資源。)
因為,無法判斷當前掛起線程時它正在執行什麼代碼。如果在安全許可權評估期間掛起持有鎖的線程,則 AppDoamin 中的其它線程可能被阻止。如果線上程正執行建構函式時掛起它,則 AppDomain 中嘗試使用該類的其它線程將被阻止。這樣容易發生死結。
方案二:
在 線程運行過程中 適當的位置(如某個完整的功能/命令後)判斷是否要繼續線程,再決定線程的命運。
1.定義一個全域變數:
int mTdFlag = 0; // 1:正常運行;2:暫停;3:停止
2. 定義一個判斷方法:
bool WaitForContinue() {if (this.mTdFlag == 3) {return false; // 返回false,線程停止 }else if (this.mTdFlag == 2) {while (mTdFlag != 1) { Thread.Sleep(200); // 假暫停;停頓時間越短,越靈敏if (this.mTdFlag == 3) {return false; // 返回false,線程停止 } } }return true; // 返回true,線程繼續}
3.修改 控制命令 事件:
private void btn_Stop_Click(object sender, EventArgs e) {this.mTdFlag = 3;//mThread.Abort(); // 終止 }private void btn_Suspend_Click(object sender, EventArgs e) {this.mTdFlag = 2;//mThread.Suspend(); // 暫停 }private void btn_Resume_Click(object sender, EventArgs e) {this.mTdFlag = 1;//mThread.Resume(); // 繼續}
4.線上程運行過程中適當的位置,判斷線程是否繼續
mThread = new Thread(() =>{try{for (int j = 0; j < 20; j++) {int vSum = 0;this.textBox1.Text += "--->";for (int i = 0; i < 100000000; i++) {if (i % 2 == 0) { vSum += i; }else{ vSum -= i; }if (i % 10000000 == 0) {this.textBox1.Text += "."; }if (!WaitForContinue()) // 返回 false 則,停止 {break;//return; } }this.textBox1.Text += string.Format("{0} => vSum = {1}\r\n", DateTime.Now.ToString(), vSum);if (!WaitForContinue()) // 返回 false 則,停止 {break;// return; } Thread.Sleep(1000); } }catch (ThreadAbortException ex) { Console.WriteLine("ThreadAbortException:{0}", ex.Message);this.textBox1.Text += ex.Message + "..."; }finally{this.textBox1.Text += "線程已結束"; } });
在表單中,解決跨線程訪問問題:在表單建構函式中添加代碼: Control.CheckForIllegalCrossThreadCalls = false;
[]