摘要
在C#中,線程的生命周期是由多個狀態(tài)組成的,這些狀態(tài)包括線程的創(chuàng)建、啟動、掛起、等待、恢復和終止。
正文
1. 創(chuàng)建線程
線程的生命周期從創(chuàng)建開始。在C#中,可以通過System.Threading.Thread
類的實例化來創(chuàng)建一個線程。創(chuàng)建線程時,需要指定一個將在該線程上執(zhí)行的方法。
Thread myThread = new Thread(new ThreadStart(MyMethod));
這里,MyMethod是一個無參方法,它定義了線程的執(zhí)行內(nèi)容。
2. 啟動線程
創(chuàng)建線程后,它處于就緒狀態(tài),等待CPU的調(diào)度。通過調(diào)用Thread
對象的Start
方法來啟動線程,使其進入可運行狀態(tài)。
一旦線程開始執(zhí)行,它會自動地調(diào)用其對應的方法。
3. 掛起線程
線程可以被顯式地掛起,即暫時停止執(zhí)行,這通常是通過調(diào)用Suspend
方法實現(xiàn)的。不過,需要注意的是,Suspend
方法在.NET Framework 2.0之后已被棄用,因為它可能導致死鎖?,F(xiàn)在建議使用其他同步技術,如ManualResetEvent
或Monitor
等。
4. 線程等待
線程在執(zhí)行過程中,可能會因為某些條件未滿足而進入等待狀態(tài)。例如,當線程調(diào)用Join
方法等待另一個線程完成時,或者使用Thread.Sleep
暫停當前線程的執(zhí)行。
myThread.Join(); // 等待myThread線程完成
Thread.Sleep(1000); // 當前線程暫停1秒
5. 恢復線程
對于被掛起的線程,可以通過調(diào)用Resume
方法來恢復其執(zhí)行。同樣地,Resume
方法也已被棄用,建議使用其他同步機制來控制線程的執(zhí)行。
6. 終止線程
線程的執(zhí)行可以通過多種方式結束:
線程一旦終止,它的狀態(tài)變?yōu)镾topped,此時它的生命周期結束。
因為我們是用Winform做線程實例,所以需要跨線程UI操作的一些技術。
示例
一個例子,點擊開始,會在文本框中每10毫秒輸出一個點。
創(chuàng)建線程
通過new 一個Thread對象并指定線程執(zhí)行函數(shù)創(chuàng)建線程。調(diào)用Start方法開啟線程
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.Invoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
通過在線程函數(shù)中調(diào)用Thread.Sleep()
暫停當前線程,使線程進入休眠狀態(tài)。此時線程會占用盡可能少的CPU時間。
線程等待
假設有線程t,在主程序中調(diào)用了t.Join()方法,該方法允許我們等待直到線程t完成。當線程t完成 時,主程序會繼續(xù)運行。借助該技術可以實現(xiàn)在兩個線程間同步執(zhí)行步驟。第一個線程會等待另一個線程完成后再繼續(xù)執(zhí)行。第一個線程等待時是處于阻塞狀態(tài)(正如暫停線程中調(diào)用 Thread.Sleep方法一樣)
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
thread.Join();
Thread thread1 = new Thread(ShowDot1);
thread1.Start();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
void ShowDot1()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue1.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
終止線程
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(ShowDot);
thread.Start();
// SpinWait 不僅僅只是空循環(huán)。謹慎實現(xiàn)后,它可以提供適用于一般情況的正確旋轉行為,
// 并且本身能夠在旋轉時間夠長(大致是內(nèi)核轉換所需的時間長度)時自行啟動上下文切換。
//有點像Sleep
SpinWait.SpinUntil(() => false, 100);
thread.Interrupt();
}
void ShowDot()
{
for (int i = 0; i < 100; i++)
{
this.BeginInvoke((() =>
{
txtValue.Text += ".";
}));
System.Threading.Thread.Sleep(10);
}
}
thread.Abort(); 這個在.Net中不支持了,只在.Net Framework中支持。
注意
在多線程編程中,正確管理線程的生命周期是非常重要的。不當?shù)木€程管理可能會導致資源泄露、死鎖或其他并發(fā)問題。因此,建議使用高級的并發(fā)和同步機制,如任務并行庫(TPL)中的Task
類,它提供了更加豐富和靈活的控制方式。
該文章在 2024/3/31 1:13:49 編輯過