在寫c#程式時,當執行一些時間較長的操作,比如複雜的計算,比如資料庫操作等等都會使介面失去響應。
要解決這些問題,第一時間就想到了用多線程。把複雜的操作指派到輔助線程執行,而主線程(一般指UI線程)可以響應使用者輸入。
經過簡單的搜尋得知啟動線程的方法:
ThreadStart ts=new ThreadStart(asyncWrok); //定義委託
Thread thread=new Thread(ts); //構造線程
thread.Start(); //啟動線程
線程就這麼簡單啟動了。(但沒有註明其銷毀,不知是否自動回收。)
例子:
private void btnExit_Click(object sender, EventArgs e) //關閉按鈕,用於測試正在運行線程時中斷程式
{
this.Close();
}
private void btnSearch_Click(object sender, EventArgs e) //線程啟動
{
if (btnSearch.Text == "&Begin")
{
btnSearch.Text = "&Cancel";
lblResult.Text = "Beginning...";
new MethodInvoker(asyncWork).BeginInvoke(null, null); //非同步委託啟動線程
//Thread thread = new Thread(new ThreadStart(asyncWork)); //構造線程
//thread.Start(); //啟動線程
}
else
{
btnSearch.Text = "&Begin";
lblResult.Text = "Cancelling...";
lblResult.Update();
}
}
private void asyncWork() //長耗時操作,這裡增加操作進度反饋。UI不能跨線程操作,所以需要調用UI線程
{
for (int i = 0; i < Int16.MaxValue; i++)
{
SetTextM(i);
}
}
delegate void SetTextCallback(int text);
private void SetTextM(int i) //將不同線程的響應寫在一個方法裡面
{
if (this.txtInc.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetTextM);
txtInc.Invoke(d, new object[] { i });
}
else
{
this.txtInc.Text = i.ToString();
}
}
但是在執行的過程中關閉視窗會出現以下錯誤:
txtInc.Invoke :"在建立視窗控制代碼之前,不能在控制項上調用 Invoke 或 BeginInvoke。" 或者是
用this.Invoke: "無法訪問已釋放的對象。"
非同步委託使用系統線程池ThreadPool,線程狀態由系統管理, 所以非同步委託和 txtInc.Invoke正常結束(是否繼續執行就不清楚。)
而用Thread thread = new Thread(new ThreadStart(asyncWork)); 方法就會報錯。
解決執行過程關閉: 調用線程的Abort()方法