C++ 标准库std::thread 实战封装+Windows多线程文件搜索

emmmm,这个文件搜索也有很多种的,我简单说下windows平台的吧。对mfc熟悉的可以用这个类CFileFind,熟悉Win32API的嘛,就可以用我下面提供的方法了,不过也不是很好,希望有更好的解决办法的伙伴在评论区留下建议。
1 线程的启动方式,例程上面用的是AfxBeginThread,后来想想,要不改成标准库中的线程函数试试看,还可以。

2 涉及到标准库中线程函数的封装,其实也没那个必要,就是玩玩。下面是我封装的一个放飞自我的线程。主线程中最好有变量控制来等待线程结束,否则可能会出问题。

template <class _Fn, class... _Args> std::thread::id BeginThread_DeTach(_Fn _Fx, _Args... _Argx)
{
	std::thread tx(_Fx, _Argx...);
	tx.detach();
	return tx.get_id();
}

3 用起来也是很简单的,直接用就好了。和AfxBeginThread差不多。

BeginThread_DeTach(SearchFileThread, &m_param);

4 下面是我的线程执行代码Windows下的多线程文件搜索。

#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef struct THREADPARAM //线程参数结构体
{
	std::string strPath;							//路径名
	std::string strFileName;						//文件名										
	struct THREADPARAM *pSelf;						//自身的指针
}MyTHREADPARAM;

std::vector<std::string> vstrSearchResult;//搜索的文件结果


MyTHREADPARAM m_param;//线程函数参数		
CMutex m_mutexThreadCount, m_mutexFileCount, m_mutexThreadParam, m_mutexPath;
UINT uThreadCount = 0;//线程数目初始化为0
int nFileCount = 0;//找到文件的数量
CEvent g_FinishEvent;	//事件对象



template <class _Fn, class... _Args> std::thread::id BeginThread_DeTach(_Fn _Fx, _Args... _Argx)
{
	std::thread tx(_Fx, _Argx...);
	tx.detach();
	return tx.get_id();
}

UINT SearchFileThread(LPVOID pParam)//工作线程入口函数
{
	m_mutexThreadParam.Lock();
	MyTHREADPARAM * m_pParam = (MyTHREADPARAM *)pParam;
	std::string strPath = m_pParam->strPath;
	std::string strFileName = m_pParam->strFileName;
	m_mutexThreadParam.Unlock();

	m_mutexThreadCount.Lock();
	uThreadCount++;
	m_mutexThreadCount.Unlock();
	HANDLE hFile;
	WIN32_FIND_DATAA *pInfo = new WIN32_FIND_DATAA;
	hFile = ::FindFirstFileA((strPath + "\\*.*").c_str(), pInfo);
	if (hFile == INVALID_HANDLE_VALUE)//未找到文件或文件夹
	{
		delete pInfo;
		m_mutexThreadCount.Lock();
		uThreadCount--;//线程即将关闭
					  
		if (uThreadCount == 0)
			g_FinishEvent.SetEvent();			//检查完成,路径错误返回	
		m_mutexThreadCount.Unlock();

		return 0;
	}
	do {
		if (pInfo->cFileName[0] == '.')
			continue;
		char cFileName[MAX_PATH];
		strcpy(cFileName, pInfo->cFileName);
		//LOG(cFileName);
		std::string strFile = cFileName;
		if (pInfo->dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)//如果得到的是文件夹
		{

			m_mutexThreadParam.Lock();

			MyTHREADPARAM *ptemp = new MyTHREADPARAM;

			ptemp->pSelf = ptemp;
			ptemp->strFileName = strFileName;
			ptemp->strPath = strPath + "\\" + strFile;//将文件夹路径传给线程函数参数
			m_mutexThreadParam.Unlock();
			//	AfxBeginThread(SearchFileThread, ptemp, THREAD_PRIORITY_NORMAL);//开始一个新的工作线程
			BeginThread_DeTach(SearchFileThread, ptemp);
			//tx.detach();

		}
		else//获取的是文件
		{
			if (strFile == strFileName)//找到要搜索的文件
			{
				m_mutexFileCount.Lock();
				nFileCount++;//文件数目加1
				m_mutexFileCount.Unlock();
				m_mutexPath.Lock();
				OutputDebugStringA(strPath.c_str());
				std::string strFilePathName;
				strFilePathName = strPath + "\\" + strFile;//文件路径及名称
				vstrSearchResult.push_back(strFilePathName);//向结果中添加一条路径
				//LOG(strFilePathName);
				m_mutexPath.Unlock();
			}
		}
	} while (::FindNextFileA(hFile, pInfo));
	::FindClose(hFile);	//搜索完毕关闭文件句柄
	delete pInfo;//释放内存
	m_mutexThreadCount.Lock();
	uThreadCount--;//工作线程即将结束
	if (uThreadCount == 0)
		g_FinishEvent.SetEvent();			//搜索完成
	m_mutexThreadCount.Unlock();

	if (m_pParam->pSelf)
	{
		delete m_pParam;   //删除掉自己
	}

	return 0;
}

void PrintResult()
{
	std::vector<std::string>::iterator Reoultiter;
	for (Reoultiter = vstrSearchResult.begin();Reoultiter != vstrSearchResult.end();++Reoultiter)
	{
		cout << *Reoultiter << endl;
	}
}


UINT StartSearchFileThread(std::string filePah, std::string fileName)//工作线程参数设置函数
{
	vstrSearchResult.clear();
	g_FinishEvent.ResetEvent();
	m_param.pSelf = nullptr;
	m_param.strPath = filePah;
	m_param.strFileName = fileName;
	//AfxBeginThread(SearchFileThread, &m_param, THREAD_PRIORITY_NORMAL);//创建工作线程
	/*std::thread t(SearchFileThread, &m_param);
	t.detach();*/
	BeginThread_DeTach(SearchFileThread, &m_param);
	WaitForSingleObject(g_FinishEvent.m_hObject, INFINITE);			//无限期等待
	PrintResult();
	return 0;
}



int main()
{
	StartSearchFileThread("E:\\\\", "hello.exe");
	//AfxBeginThread(StartSearchFileThread, NULL, THREAD_PRIORITY_NORMAL);//创建工作线程
	system("pause");
	return 0;
}

你可能感兴趣的:(Windows_C++)