多線程編程能顯著提升多核 CPU 利用率。本文提供一個可復用的 C++ 線程池實現:基於 Windows 信號量同步、臨界區互斥、動態任務隊列,支持任務異常捕獲與優雅關閉。附帶 Excel 導出異步寫入的實戰範例。
class WorkItemBase {
virtual void DoWork(void* pThreadContext) = 0; // 具體任務邏輯
virtual void Abort() = 0; // 池銷毀時調用
friend class CWorkQueue;
};
Create(nThreads, threadDataArray):創建 N 個工作線程,每線程可傳遞私有上下文指針。InsertWorkItem(WorkItemBase*):線程安全入隊,釋放信號量喚醒一線程。Destroy(waitSec):等待隊列清空 → 設置退出事件 → 等待所有線程結束 → 清理資源。Semaphore(任務計數)、Event(退出通知)、CriticalSection(隊列互斥)。unsigned long __stdcall CWorkQueue::ThreadFunc(void* pParam) {
THREAD_CONTEXT* ctx = (THREAD_CONTEXT*)pParam;
CWorkQueue* pQueue = ctx->pWorkQueue;
void* pThreadData = ctx->pThreadData;
for (;;) {
DWORD ret = WaitForMultipleObjects(2, pQueue->m_phSyncObjects, FALSE, INFINITE);
switch (ret - WAIT_OBJECT_0) {
case 0: // ABORT_EVENT
delete ctx; return 0;
case 1: // SEMAPHORE
WorkItemBase* item = pQueue->RemoveWorkItem();
if (item) item->DoWork(pThreadData);
break;
}
}
}
bool CWorkQueue::InsertWorkItem(WorkItemBase* item) {
EnterCriticalSection(&m_CriticalSection);
m_pWorkItemQueue->push(item);
LeaveCriticalSection(&m_CriticalSection);
return ReleaseSemaphore(m_phSyncObjects[SEMAPHORE_INDEX], 1, NULL);
}
WorkItemBase* CWorkQueue::RemoveWorkItem() {
EnterCriticalSection(&m_CriticalSection);
WorkItemBase* item = m_pWorkItemQueue->front();
m_pWorkItemQueue->pop();
LeaveCriticalSection(&m_CriticalSection);
return item;
}
class CWorkItem : public WorkItemBase {
vector m_data;
String m_filePath;
public:
void SetWriteContent(const vector& data) { m_data = data; }
void SetExcelPath(const String& path) { m_filePath = path; }
void DoWork(void* ctx) override {
OperateExcel op;
String err;
op.WriteDateToExcel(m_filePath, m_data, err);
delete this; // 自毀
}
void Abort() override { delete this; }
};
CWorkQueue pool;
pool.Create(4); // 4 條工作線程
CWorkItem* item1 = new CWorkItem();
item1->SetWriteContent(data);
item1->SetExcelPath("D:\\report1.xls");
pool.InsertWorkItem(item1);
CWorkItem* item2 = new CWorkItem();
item2->SetWriteContent(data);
item2->SetExcelPath("D:\\report2.xls");
pool.InsertWorkItem(item2);
pool.Destroy(5); // 最多等 5 秒清空隊列
pThreadData(如資料庫連接、COM 初始化狀態)。Destroy 先等隊列清空,再廣播退出事件,最後 Abort 清理殘留任務。SetThreadIdealProcessor 綁核優化。