多线程搜索系统盘文件
说明:
1.利用线程进行文件扫描。每遇到一个文件夹,创建一条线程进去搜索文件。(与递归类似)
注意点:
1.vector容器不安全。要设置临界区,不会多条线程同时对vector进行操作,实现同步。(原子操作)
2.具体步骤。
//临界区
CRITICAL_SECTION g_cs;
//初始化
InitializeCriticalSection(&g_cs);
//上锁
EnterCriticalSection(&g_cs);
//解锁
LeaveCriticalSection(&g_cs);
//释放
DeleteCriticalSection(&g_cs);
3.对线程进行计数。
加数
InterlockedAdd(&g_lThreadNum, 1);
减数
InterlockedAdd(&g_lThreadNum, -1);
4.设置多线程退出标识。HANDLE g_hExitEvent; //信号量。标记线程退出
因为是多线程进行操作,要保证线程全部退出后,主线程才退出,程序结束。
//创建事件消息
g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//如果全部线程退出,激活该信号量
SetEvent(&g_hExitEvent);
//只需等待信号量,即退出程序,不需要使用WaitForMultiObject(),会造成长时间等待、阻塞。
WaitForSingleObject(g_hExitEvent, INFINITE);
5.对容器进行释放
for (auto g_h_Threads: g_hThreads)
{
CloseHandle(g_h_Threads);
}
源代码: #include "stdafx.h" #include <Windows.h> #include <stdlib.h> #include <iostream> using namespace std; #include <process.h> #include <vector> vector<HANDLE> g_hThreads; //存放线程的句柄 long g_lNum = 0; //文件数目 long g_lFileNum=0; //文件夹数目 long g_lThreadNum = 0; //线程数目 HANDLE g_hExitEvent; //标记线程退出 CRITICAL_SECTION g_cs; //临界区 struct ThreadData { wstring m_strBeginFileName; wstring m_strSearchFileName; wstring m_strFilte; }; //文件路径标准化 "C:\\" wstring MakeStdName(wstring &wstrFileName) { if (wstrFileName.back() != '\\') { return (wstrFileName + L"\\"); } else return wstrFileName; } unsigned _stdcall FindFileThread(void * lParam) { ThreadData *pData = (ThreadData *)lParam; WIN32_FIND_DATAW FileData = {0}; HANDLE hFindFile = FindFirstFileW((MakeStdName(pData->m_strBeginFileName) + (pData->m_strFilte)).c_str(),&FileData); //可能打开文件失败,但是下面依然创建线程。 if (hFindFile != INVALID_HANDLE_VALUE) { do { if (FileData.cFileName, L"." == 0) continue; if (FileData.cFileName, L".." == 0) continue; if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { ThreadData *pTempData = new ThreadData; pTempData->m_strBeginFileName =MakeStdName(pData->m_strBeginFileName) + FileData.cFileName; pTempData->m_strFilte = pData->m_strFilte; pTempData->m_strSearchFileName = pData->m_strSearchFileName; //上锁 EnterCriticalSection(&g_cs); InterlockedAdd(&g_lThreadNum, 1); g_hThreads.push_back((HANDLE)_beginthreadex(NULL, 0, FindFileThread, pTempData, 0, NULL)); //解锁 LeaveCriticalSection(&g_cs); } else { if (wcsstr(FileData.cFileName, pData->m_strSearchFileName.c_str()) != NULL) { printf("文件:%ls\r\n", (MakeStdName(pData->m_strBeginFileName) + FileData.cFileName).c_str()); InterlockedAdd(&g_lNum, 1); } } } while (FindNextFileW(hFindFile, &FileData)); } delete pData; InterlockedAdd(&g_lThreadNum, -1); if (g_lThreadNum == 0) { SetEvent(&g_hExitEvent); } return g_lNum; } int _tmain(int argc, _TCHAR* argv[]) { DWORD dwBeginTime = GetTickCount(); InitializeCriticalSection(&g_cs); g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ThreadData *pTempData = new ThreadData; pTempData->m_strBeginFileName = L"C:\\"; pTempData->m_strFilte = L"*.*"; pTempData->m_strSearchFileName = L"ntdll"; InterlockedAdd(&g_lThreadNum, 1); g_hThreads.push_back((HANDLE)_beginthreadex(NULL, 0, FindFileThread, pTempData, 0, NULL)); WaitForSingleObject(g_hExitEvent, INFINITE); //for (auto g_h_Threads: g_hThreads) //{ // CloseHandle(g_h_Threads); //} DeleteCriticalSection(&g_cs); DWORD dwTime = GetTickCount() - dwBeginTime; _endthread(); printf("文件夹个数:%d,ntdll文件个数: %d\r\n", g_lFileNum, g_lNum); printf("共用%d秒\r\n", dwTime / 1000); system("pause"); return 0; }