Thread.Join() 讓呼叫線程阻塞,直到目標線程結束(正常返回或拋出未捕獲異常)。實現「線程插入」效果:主線程等待子線程完成再繼續。
| 方法 | 說明 |
|---|---|
Join() | 無限期等待 |
Join(TimeSpan) | 等待指定時間,超時返回 false |
Join(int milliseconds) | 等待指定毫秒,超時返回 false |
using System;
using System.Threading;
class JoinDemo
{
static void Main()
{
Console.WriteLine("主線程開始: {0}", DateTime.Now.TimeOfDay);
Thread t1 = new Thread(Work) { Name = "Worker-1" };
Thread t2 = new Thread(Work) { Name = "Worker-2" };
t1.Start();
t2.Start();
Console.WriteLine("主線程等待 t1 結束...");
t1.Join(); // 阻塞直到 t1 結束
Console.WriteLine("t1 結束,等待 t2 (最多 2 秒)...");
bool finished = t2.Join(TimeSpan.FromSeconds(2));
if (finished)
Console.WriteLine("t2 正常結束");
else
Console.WriteLine("t2 超時未結束,主線程繼續");
Console.WriteLine("主線程結束: {0}", DateTime.Now.TimeOfDay);
}
static void Work()
{
Thread.Sleep(3000); // 模擬工作 3 秒
Console.WriteLine("{0} 完成", Thread.CurrentThread.Name);
}
}
foreach (var t in threads) t.Join();
WaitHandle[] handles = threads.Select(t => (WaitHandle)t).ToArray();
// WaitHandle.WaitAll(handles); // .NET Framework 不支援 Thread 直接 WaitAll
// 需自行包裝 ManualResetEvent 或改用 Task
var tasks = new Task[3];
for (int i = 0; i < 3; i++)
tasks[i] = Task.Run(() => Work(i));
Task.WaitAll(tasks); // 並行等待,更簡潔高效
Join 的線程進入 WaitSleepJoin 狀態。Join 立即返回。| 陷阱 | 後果 | 解決 |
|---|---|---|
| 主線程 Join UI 線程 | UI 凍結、死鎖 | 用 async/await、BackgroundWorker、Task.Run |
| 互相 Join | 死鎖 | 避免循環等待,重構架構 |
| Join 已中止線程 | 拋出 ThreadStateException | 檢查 ThreadState 或捕獲異常 |
(原文包含兩張圖片,展示 Join 阻塞喚醒流程、串行/並行等待對比)