作者:40740 | 来源:互联网 | 2023-09-23 20:17
说明:1.利用线程进行文件扫描。每遇到一个文件夹,创建一条线程进去搜索文件。(与递归类似)注意点:1.vector容器不安全。要设置临界区,不会多条线程同时对vector进行操作,实现同步。(原子
说明:
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
#include
#include
using namespace std;
#include
#include
vector 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;
}