// 任務單元:代表一個可獨立計算、保存、恢復的工作塊
struct ComputeTask {
int taskId; // 全局唯一 ID
int startIndex, endIndex; // 數組切片範圍
std::vector<double> inputData; // 輸入數據 (或共享內存指針+偏移)
std::vector<double> resultData; // 計算結果
enum Status { PENDING, RUNNING, COMPLETED, FAILED } status;
int retryCount;
std::string errorMsg;
// 序列化保存到文件
void save(const std::string& filename) const;
// 從文件恢復
static ComputeTask load(const std::string& filename);
};
task_.bin (二進制) 或 .json。progress.json:記錄所有 Task ID、狀態、文件路徑、時間戳。progress.json,跳過 COMPLETED 任務,重試 FAILED 任務。Tasks(id, start_idx, end_idx, status, result_blob, error, created_at, updated_at)。mmap / CreateFileMapping 到文件,計算結果直接寫入映射區。FlushViewOfFile)。// 工作線程主循環
UINT ComputeThread(LPVOID pParam) {
ComputeManager* mgr = (ComputeManager*)pParam;
while (true) {
ComputeTask task = mgr->getNextPendingTask(); // 線程安全獲取
if (task.taskId == -1) break; // 無任務退出
task.status = ComputeTask::RUNNING;
mgr->updateTaskStatus(task); // 持久化狀態
try {
// 核心計算邏輯
task.resultData = computeSlice(task.inputData);
task.status = ComputeTask::COMPLETED;
} catch (const std::exception& e) {
task.status = ComputeTask::FAILED;
task.errorMsg = e.what();
task.retryCount++;
if (task.retryCount <= MAX_RETRY) {
// 重新入隊重試
mgr->requeueTask(task);
Sleep(RETRY_DELAY_MS);
continue;
}
}
// 保存結果 (成功或最終失敗)
task.save(mgr->getTaskFilePath(task.taskId));
mgr->updateTaskStatus(task);
}
return 0;
}
AfxBeginThread 創建工作線程,傳遞管理器指針。CCriticalSection / CMutex 保護。PostMessage(WM_USER_PROGRESS, ...) 更新進度條/列表。ComputeManager*,析構時發送停止信號、等待線程結束、彙總結果。progress.json → 重建任務隊列 → 標記 COMPLETED 任務為跳過,FAILED 重置為 PENDING (重試計數保留)。// progress.json 結構
{
"version": 1,
"totalTasks": 100,
"completed": 45,
"tasks": [
{"id": 0, "status": "COMPLETED", "file": "task_0.bin", "time": "2024-01-15T10:00:00Z"},
{"id": 1, "status": "FAILED", "retry": 2, "error": "div by zero", "file": "", "time": "..."},
...
]
}
// 讀取/寫入封裝 (使用 nlohmann/json 或 MFC CJsonObject)
void ComputeManager::loadProgress() { /* 解析 JSON 重建隊列 */ }
void ComputeManager::saveProgress() { /* 序列化寫入文件 */ }
「自動保存 + 錯誤恢復」核心在於將計算拆解為可獨立持久化的 Task,配合進度元數據文件/數據庫記錄狀態。MFC 多線程下,使用文件系統或 SQLite落地結果,線程池 + 任務隊列 + 重試邏輯實現斷點續傳,UI 通過消息泵異步更新進度。