首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

多執行緒技術實現高效檔案搜尋:從遞迴到並行的效能躍升

     編輯:關於VC++

前言

傳統的檔案搜尋採用單執行緒遞迴遍歷目錄樹的方式,不僅程式碼複雜,且在目錄層級較深時效率極低。本文介紹如何利用多執行緒技術實現並行檔案搜尋,大幅提升搜尋效能。

核心設計思想

採用「發現一個目錄即建立一個執行緒」的策略,實現同步並行搜尋:

  • 主執行緒負責協調與結果收集
  • 每個子目錄由獨立執行緒處理
  • 檔案比對在執行緒內部完成
  • 透過同步機制確保執行緒安全

關鍵 Windows API

HANDLE FindFirstFile(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);
BOOL FindNextFile(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData);

執行緒參數結構與同步物件

typedef struct tagTHREADPARAM {
    CString strPath;      // 搜尋路徑
    CString strFileName;  // 目標檔案名
} THREADPARAM, *LPTHREADPARAM;

// 同步物件
CMutex m_mutexThreadCount;  // 執行緒計數器保護
CMutex m_mutexThreadParam;  // 參數結構保護
CMutex m_mutexPath;         // 結果陣列保護
CEvent m_event;             // 完成通知事件
UINT uThreadCount = 0;      // 活躍執行緒數
CStringArray m_strPathArray; // 搜尋結果儲存

執行緒處理函數核心邏輯

UINT GetFilePathThreadProc(LPVOID pParam)
{
    if (!pParam) AfxEndThread(0);
    
    THREADPARAM* pThreadParam = (THREADPARAM*)pParam;
    CString strPath = pThreadParam->strPath;
    CString strFileName = pThreadParam->strFileName;
    
    // 增加執行緒計數
    m_mutexThreadCount.Lock();
    uThreadCount++;
    m_mutexThreadCount.Unlock();
    
    WIN32_FIND_DATA* pInfo = new WIN32_FIND_DATA;
    HANDLE hFile = ::FindFirstFile(strPath + _T("\\*.*"), pInfo);
    
    if (hFile == INVALID_HANDLE_VALUE) {
        delete pInfo;
        // 減少計數並檢查是否全部完成
        m_mutexThreadCount.Lock();
        uThreadCount--;
        if (uThreadCount == 0) m_event.SetEvent();
        m_mutexThreadCount.Unlock();
        return 0;
    }
    
    do {
        // 跳過 "." 和 ".." 目錄
        if (pInfo->cFileName[0] == '.') continue;
        
        CString strFile = pInfo->cFileName;
        
        if (pInfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            // 目錄:建立新執行緒遞迴搜尋
            m_mutexThreadParam.Lock();
            m_param.strPath = strPath + _T("\\") + strFile;
            m_param.strFileName = strFileName;
            AfxBeginThread(GetFilePathThreadProc, &m_param, THREAD_PRIORITY_NORMAL);
            m_mutexThreadParam.Unlock();
        } else {
            // 檔案:比對檔案名
            if (strFile == strFileName) {
                m_mutexPath.Lock();
                m_strPathArray.Add(strPath + _T("\\") + strFile);
                m_mutexPath.Unlock();
            }
        }
    } while (::FindNextFile(hFile, pInfo));
    
    ::FindClose(hFile);
    delete pInfo;
    
    // 執行緒結束,減少計數
    m_mutexThreadCount.Lock();
    uThreadCount--;
    if (uThreadCount == 0) m_event.SetEvent();
    m_mutexThreadCount.Unlock();
    
    return 0;
}

搜尋啟動與等待機制

void GetFilePath()
{
    m_event.ResetEvent();
    uThreadCount = 0;
    m_strPathArray.RemoveAll();
    
    m_param.strPath = m_strPath;
    m_param.strFileName = m_strFileName;
    
    // 啟動初始執行緒
    AfxBeginThread(GetFilePathThreadProc, &m_param, THREAD_PRIORITY_NORMAL);
    
    // 等待所有執行緒完成
    ::WaitForSingleObject(m_event.m_hObject, INFINITE);
    
    if (m_strPathArray.GetUpperBound() == -1) {
        AfxMessageBox(_T("未找到檔案"));
        return;
    }
    
    for (int i = 0; i < m_strPathArray.GetSize(); i++) {
        AfxMessageBox(m_strPathArray.GetAt(i));
    }
}

中途終止搜尋機制

維護執行緒物件陣列,需要終止時呼叫:

BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);
BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);

執行效果展示

多執行緒檔案搜尋程式執行畫面

開發環境

  • VC++ 6.0
  • Windows 2000
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved