多執行緒與多進程程式設計中,資料交換與同步控制是核心課題。本文系統整理 Windows 平台下的主流 IPC(進程間通訊)與同步原語,並提供 VC++ 與 .NET 兩套實作範例,供開發者快速查閱與選型。
| 類別 | 機制 | 適用場景 | 跨進程 |
|---|---|---|---|
| 共享記憶體 | 全域變數 / CreateFileMapping + MapViewOfFile | 高速、大量資料交換 | 是 |
| 核心物件 | 命名管道、匿名管道 | 父子進程、本機高可靠傳輸 | 是(命名管道) |
| 訊息機制 | 視窗訊息 (PostMessage/SendMessage) | UI 執行緒通知、簡單命令傳遞 | 否(需相同桌面) |
| 網路通訊 | Socket (TCP/UDP) | 跨機器、異構系統整合 | 是 |
| 參數傳遞 | 命令列參數、環境變數、CreateThread 的 lpParameter | 啟動階段設定 | 部分 |
DWORD WINAPI ThreadProc(LPVOID lParam);
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, lParam, 0, &dwThreadId);
// 等待結束
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
// 取得退出碼
GetExitCodeThread(hThread, &exitCode);
// 強制終止(極不推薦)
TerminateThread(hThread, 0);
using System.Threading;
Thread th = new Thread(new ParameterizedThreadStart(ThreadProc));
th.IsBackground = true; // 主程式結束時自動終止
th.Start(lParam);
th.Join(); // 等待結束
th.Abort(); // 強制中止(慎用)
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
BOOL bRet = CreateProcess(
pFileName, pArgs, NULL, NULL, FALSE,
0, pEnv, NULL, &si, &pi);
// 同步等待
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
GetExitCodeProcess(pi.hProcess, &exitCode);
using System.Diagnostics;
Process p = new Process();
p.StartInfo.FileName = ...;
p.StartInfo.Arguments = ...;
p.Start();
p.WaitForExit();
int exitCode = p.ExitCode;
p.Kill(); // 強制終止
// VC++
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs); // 或 InitializeCriticalSectionAndSpinCount(&cs, 2000)
EnterCriticalSection(&cs);
// ... 受保護區段 ...
LeaveCriticalSection(&cs);
DeleteCriticalSection(&cs);
// .NET
lock (syncObj) { ... }
// 或
Monitor.Enter(syncObj);
try { ... } finally { Monitor.Exit(syncObj); }
注意:跨進程需置於共享記憶體;優先使用 RAII 包裝類別防止忘記釋放。
// VC++
HANDLE hMutex = CreateMutex(NULL, FALSE, L"Global\\MyMutex"); // 命名互斥體
WaitForSingleObject(hMutex, INFINITE); // 返回 WAIT_ABANDONED 表示前擁有者異常終止
ReleaseMutex(hMutex);
CloseHandle(hMutex);
// .NET
using System.Threading;
Mutex m = new Mutex(false, "Global\\MyMutex");
m.WaitOne();
m.ReleaseMutex();
// VC++
HANDLE hSem = CreateSemaphore(NULL, 1, 5, L"Global\\MySem"); // 初始 1,最大 5
WaitForSingleObject(hSem, INFINITE); // 計數 -1
ReleaseSemaphore(hSem, 1, NULL); // 計數 +1
// .NET
Semaphore sem = new Semaphore(1, 5, "Global\\MySem");
sem.WaitOne();
sem.Release(1);
進程終止時信號量不會自動釋放,需謹慎設計。
// VC++ 事件控制執行緒迴圈(優於輪詢旗標)
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 手動重設
// Worker
while (TRUE) {
DWORD dw = WaitForSingleObject(hEvent, 1);
if (dw == WAIT_OBJECT_0) break;
DoWork();
}
// Stopper
SetEvent(hEvent);
WaitForSingleObject(hThread, INFINITE);
適用於引用計數、簡單計數器。VC++ 使用 InterlockedIncrement 等;.NET 使用 System.Threading.Interlocked 類別。僅鎖定資料而非程式碼區段。
單核心下無意義;長區段會導致 CPU 100% 忙等待。Windows 提供 SRWLOCK (Vista+) 兼具自旋與核心等待優勢。
SendMessage、回呼函式或阻塞性 APItry/finally 或 RAII 確保釋放TerminateThread/Process 導致鎖永不釋放掌握這些機制的特性與適用邊界,是撰寫高效、穩定並發程式的基石。