运用多线程技术实现文件的快速搜索

概述

操作系统一般都提供了文件搜索的功能,但采用的是顺序搜索,搜索效率很底。而且按此法编程十分烦琐,在目录层次很多时,往往不好处理。本文采用多线程技术实现文件的快速搜索,代码量很少,执行效率极高。
其基本思想其实很简单,就是找到一个目录就开辟一个线程,文件的话当然在线程内就处理了。这样实现了同步搜索,速度当然快起来了。

VC具体实现

搜索用到两个win32的两个函数

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

建立线程函数

首先要定义线程的参数结构用于文件信息的传递:

 
   
typedef struct tagTHREADPARAM {

	CString strPath;

	CString strFileName;

}THREADPARAM  m_param;

因为线程要操纵全局变量,所以定义互斥体:

CMutex m_mutexThreadCount,m_mutexThreadParam,m_mutexPath;

如果搜索完毕或搜索终止,要有事件通知,于是创建一个事件:

 
   
CEvent m_event(FALSE,FALSE,NULL,NULL);



UINT uThreadCount=0;//产生的线程数

CStringArray m_strPathArray;//存放搜索到的文件路径数组

//线程函数

UINT GetFilePathThreadProc(LPVOID pParam)

{

	if(pParam==NULL)

		AfxEndThread(NULL);	

	THREADPARAM * m_pParam=(THREADPARAM *)pParam;

	CString strPath=m_pParam->strPath;

	CString strFileName=m_pParam->strFileName;

	m_mutexThreadCount.Lock();

	uThreadCount++;

	m_mutexThreadCount.Unlock();

	HANDLE hFile;

	WIN32_FIND_DATA *pInfo=new WIN32_FIND_DATA;

	hFile = ::FindFirstFile(strPath+"\\*.*",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;

		char cFileName[MAX_PATH];

		strcpy(cFileName,pInfo->cFileName);

		CString strFile=cFileName;

		if(pInfo->dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)

		{

		    //如果是目录,则开辟新的搜索线程

			m_mutexThreadParam.Lock();

			m_param.strPath=strPath+"\\"+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+"\\"+strFile);

				m_mutexPath.Unlock();

				m_mutexThreadCount.Lock();

				uThreadCount--;

				if(uThreadCount==0)

					m_event.SetEvent();

				m_mutexThreadCount.Unlock();	

				return 0;

			}

		}		

	}

	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;

	m_param.m_pListInfo=&m_ListInfo;

	//启动线程 

	AfxBeginThread(GetFilePathThreadProc,&m_param, THREAD_PRIORITY_NORMAL); 

	//等待搜索完成或终止事件的发生

	::WaitForSingleObject(m_event.m_hObject,INFINITE); 

	if(m_strPathArray.GetUpperBound()==-1){

		AfxMessageBox("没找到文件",MB_OK|MB_ICONINFORMATION);return;}

	for(int i=0;i<m_strPathArray.GetSize();i++)

	{

		AfxMessageBox(m_strPathArray.GetAt(i),MB_OK|MB_ICONINFORMATION);

	}

}

停止搜索

如果想中途停止搜索,只需先将线程对象存放于一线程对象数组,当然每增加一个线程则添加一个线程对象到数组,每返回一个线程,则将该线程对象从数组中删除。这样在你想终止搜索时,可操作这些线程对象即可达到目的。具体调用两个函数:

 
   
BOOL GetExitCodeThread(HANDLE hThread,LPDWORD lpExitCode);

BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);

BOOL GetExitCodeThread(

  HANDLE hThread,      // handle to the thread

  LPDWORD lpExitCode   // address to receive termination status

);

BOOL TerminateThread(

  HANDLE hThread,    // handle to thread

  DWORD dwExitCode   // exit code

);


程序实现的具体情况请参见源代码。本文在VC++6.0和Windows2000环境中编译通过。

你可能感兴趣的:(多线程)