.NET 使用 System.Threading.Thread 類別管理線程。建立線程需傳入 ThreadStart 委派(無參數、無回傳值方法):
Thread t1, t2;
private void Form_Load(object sender, EventArgs e) {
t1 = new Thread(new ThreadStart(BackgroundProcess));
t1.Start();
}
private void BackgroundProcess() {
int i = 1;
while (true) {
// UI 更新需跨線程 Marshal(見下文)
listBox1.Items.Add($"Iterations: {i++}");
Thread.Sleep(2000);
}
}
| 方法 | 用途 | 備註 |
|---|---|---|
Sleep(ms) | 暫停指定毫秒 | 立即進入等待 |
| 無限期暫停 | 需 Interrupt() 喚醒 | |
| 掛起線程 | 已過時,非安全點不會立即掛起 | |
| 恢復掛起 | 配合 Suspend 使用 | |
| 強制終止 | 拋出 ThreadAbortException,需 catch 處理 | |
| 等待線程結束 | 回傳 bool 表示是否在時間內結束 |
// 停止線程範例
private void btnStop_Click(object sender, EventArgs e) {
t1.Abort(); // 簡單粗暴,生產環境建議用取消權杖
}
線程方法無參數、無回傳,解決方案:將參數與結果封裝於類別欄位,完成時觸發事件通知主線程。
public delegate void CalcCompletedEventHandler(double result);
public class SquareCalculator {
public double Value { get; set; }
public double Result { get; private set; }
public event CalcCompletedEventHandler Completed;
public void CalcSquare() {
Result = Value * Value;
Completed?.Invoke(Result); // 在工作線程觸發
}
}
// 使用
private void btnCalc_Click(object sender, EventArgs e) {
var calc = new SquareCalculator { Value = 30 };
calc.Completed += (result) => {
// 注意:此處仍在工作線程,更新 UI 需 Invoke
this.Invoke(new Action(() => MessageBox.Show($"平方: {result}")));
};
Thread t = new Thread(calc.CalcSquare);
t.Start();
}
public void CalcSquareSync() {
lock (typeof(SquareCalculator)) { // 鎖定型別物件
Result = Value * Value;
}
}
確保同一時間僅有一線程進入關鍵區段。
t2 = new Thread(calc.CalcSquare);
t2.Start();
if (t2.Join(500)) { // 等待最多 500ms
MessageBox.Show(calc.Result.ToString());
} else {
MessageBox.Show("計算逾時");
}
.NET 4.5+ 建議使用 Task.Run、async/await、CancellationToken 取代手動 Thread 管理,程式碼更簡潔、例外處理更完善、支援進度回報與組合。
// 現代寫法範例
private async void btnModern_Click(object sender, EventArgs e) {
var cts = new CancellationTokenSource();
try {
double result = await Task.Run(() => CalcSquareAsync(30, cts.Token), cts.Token);
MessageBox.Show($"結果: {result}");
} catch (OperationCanceledException) {
MessageBox.Show("已取消");
}
}
private double CalcSquareAsync(double v, CancellationToken ct) {
ct.ThrowIfCancellationRequested();
Thread.Sleep(1000); // 模擬耗時運算
return v * v;
}
Windows Forms / WPF 僅允許 UI 線程存取控制項。跨線程更新必須透過 Control.Invoke / Dispatcher.Invoke:
listBox1.Invoke(new Action(() => listBox1.Items.Add("新項目")));
掌握 Thread 基礎操作有助於理解底層機制,但實務開發請優先採用 Task 平行程式庫 (TPL)、async/await、CancellationToken 等現代模式,配合 Concurrent 集合與 SemaphoreSlim 等同步原語,打造高效、可維護的多線程應用。