手机
当前位置:查字典教程网 >编程开发 >C语言 >C++实现多线程查找文件实例
C++实现多线程查找文件实例
摘要:主要是多线程的互斥文件的查找多线程互斥的框架复制代码代码如下://线程函数UINTFinderEntry(LPVOIDlpParam){//...

主要是多线程的互斥 文件 的查找

多线程互斥的框架

复制代码 代码如下://线程函数

UINT FinderEntry(LPVOID lpParam)

{

//CRapidFinder通过参数传递进来

CRapidFinder* pFinder = (CRapidFinder*)lpParam;

CDirectoryNode* pNode = NULL;

BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活

//循环处理m_listDir列表中的目录

while (1)

{

//从列表中取出一个目录

::EnterCriticalSection(&pFinder->m_cs);

if (pFinder->m_listDir.IsEmpty()) //目录列表为空,当前线程不激活,所以bAactive=FALSE

{

bActive = FALSE;

}

else

{

pNode = pFinder->m_listDir.GetHead(); //得到一个目录

pFinder->m_listDir.Remove(pNode); //从目录列表中移除

}

::LeaveCriticalSection(&pFinder->m_cs);

//如果停止当前线程

if (bActive == FALSE)

{

//停止当前线程

//线程数--

pFinder->m_nThreadCount--;

//如果当前活动线程数为0,跳出,结束

if (pFinder->m_nThreadCount == 0)

{

::LeaveCriticalSection(&pFinder->m_cs);

break;

}

::LeaveCriticalSection(&pFinder->m_cs);

//当前活动线程数不为0,等待其他线程向目录列表中加目录

::ResetEvent(pFinder->m_hDirEvent);

::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);

//运行到这,就说明其他线程唤醒了本线程

pFinder->m_nThreadCount++; //激活了自己的线程,线程数++

bActive = TRUE; //当前线程活了

continue; //跳到while,

}

//从目录列表中成功取得了目录

<span> </span>......................

//if (pNode)

//{

// delete pNode;

// pNode = NULL;

//}

}//end while

//促使一个搜索线程从WaitForSingleObject返回,并退出循环

::SetEvent(pFinder->m_hDirEvent);

//判断此线程是否是最后一个结束循环的线程,如果是就通知主线程

if (::WaitForSingleObject(pFinder->m_hDirEvent,0) != WAIT_TIMEOUT)

{

::SetEvent(pFinder->m_hExitEvent);

}

return 1;

}

查找文件 的框架:

复制代码 代码如下://从目录列表中成功取得了目录

WIN32_FIND_DATA fileData;

HANDLE hFindFile;

//生成正确的查找字符串

if (pNode->szDir[strlen(pNode->szDir)-1] != '')

{

strcat(pNode->szDir,"");

}

strcat(pNode->szDir, "*.*");

//查找文件的框架

hFindFile = ::FindFirstFile(pNode->szDir, &fileData);

if (hFindFile != INVALID_HANDLE_VALUE )

{

do

{

//如果是当前目录,跳过

if (fileData.cFileName[0] == '.')

{

continue;

}

//如果是目录

if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

{

//将当前目录加入到目录列表

。。。。。。

//使一个线程从非活动状态变成活动状态

::SetEvent(pFinder->m_hDirEvent);

}

else //如果是文件

{

。。。。。。。。。。。。。

}

} while (::FindNextFile(hFindFile, &fileData));

}

所有代码main.cpp:

复制代码 代码如下:#include "RapidFinder.h"

#include <stddef.h>

#include <stdio.h>

#include <process.h>

//m_nMaxThread 是const int类型,只能通过这种方式初始化

CRapidFinder::CRapidFinder(int nMaxThread):m_nMaxThread(nMaxThread)

{

m_nResultCount = 0;

m_nThreadCount = 0;

m_listDir.Construct(offsetof(CDirectoryNode, pNext)); //offsetof在stddef.h头文件中

::InitializeCriticalSection(&m_cs);

m_szMatchName[0] = '';

m_hDirEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);

m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);

}

CRapidFinder::~CRapidFinder()

{

::DeleteCriticalSection(&m_cs);

::CloseHandle(m_hDirEvent);

::CloseHandle(m_hExitEvent);

}

BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName)

{

//定义两个字符串

char string[MAX_PATH];

char strSearch[MAX_PATH];

strcpy(string, lpszFileName);

strcpy(strSearch, m_szMatchName);

//将字符串大写

_strupr(string);

_strupr(strSearch);

//比较string中是否含有strSearch

if (strstr(string, strSearch) != NULL)

{

return TRUE;

}

return FALSE;

}

//线程函数

UINT FinderEntry(LPVOID lpParam)

{

//CRapidFinder通过参数传递进来

CRapidFinder* pFinder = (CRapidFinder*)lpParam;

CDirectoryNode* pNode = NULL;

BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活

//循环处理m_listDir列表中的目录

while (1)

{

//从列表中取出一个目录

::EnterCriticalSection(&pFinder->m_cs);

if (pFinder->m_listDir.IsEmpty()) //目录列表为空,当前线程不激活,所以bAactive=FALSE

{

bActive = FALSE;

}

else

{

pNode = pFinder->m_listDir.GetHead(); //得到一个目录

pFinder->m_listDir.Remove(pNode); //从目录列表中移除

}

::LeaveCriticalSection(&pFinder->m_cs);

//如果停止当前线程

if (bActive == FALSE)

{

//停止当前线程

::EnterCriticalSection(&pFinder->m_cs);

pFinder->m_nThreadCount--;

//如果当前活动线程数为0,跳出,结束

if (pFinder->m_nThreadCount == 0)

{

::LeaveCriticalSection(&pFinder->m_cs);

break;

}

::LeaveCriticalSection(&pFinder->m_cs);

//当前活动线程数不为0,等待其他线程向目录列表中加目录

::ResetEvent(pFinder->m_hDirEvent);

::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);

//运行到这,就说明其他线程向目录列表中加入了新的目录

::EnterCriticalSection(&pFinder->m_cs);

pFinder->m_nThreadCount++; //激活了自己的线程,线程数++

::LeaveCriticalSection(&pFinder->m_cs);

bActive = TRUE; //目录不再为空

continue; //跳到while,重新在目录列表中取目录

}

//从目录列表中成功取得了目录

WIN32_FIND_DATA fileData;

HANDLE hFindFile;

//生成正确的查找字符串

if (pNode->szDir[strlen(pNode->szDir)-1] != '')

{

strcat(pNode->szDir,"");

}

strcat(pNode->szDir, "*.*");

//查找文件的框架

hFindFile = ::FindFirstFile(pNode->szDir, &fileData);

if (hFindFile != INVALID_HANDLE_VALUE )

{

do

{

//如果是当前目录,跳过

if (fileData.cFileName[0] == '.')

{

continue;

}

//如果是目录

if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

{

//将当前目录加入到目录列表

CDirectoryNode* p = new CDirectoryNode;

strncpy(p->szDir, pNode->szDir, strlen(pNode->szDir)-3); //将pNode后面的*.*三位去掉

strcat(p->szDir, fileData.cFileName);

::EnterCriticalSection(&pFinder->m_cs);

pFinder->m_listDir.AddHead(p);

::LeaveCriticalSection(&pFinder->m_cs);

// 现在的p刚加入列表,就要delete,肯定会出错

//delete p;

//p = NULL;

//使一个线程从非活动状态变成活动状态

::SetEvent(pFinder->m_hDirEvent);

}

else //如果是文件

{

//判断是否为要查找的文件

if (pFinder->CheckFile(fileData.cFileName)) //符合查找的文件

{

//打印

::EnterCriticalSection(&pFinder->m_cs);

pFinder->m_nResultCount++;

::LeaveCriticalSection(&pFinder->m_cs);

printf("find %d:%sn", pFinder->m_nResultCount, fileData.cFileName);

}

}

} while (::FindNextFile(hFindFile, &fileData));

}

//if (pNode)

//{

// delete pNode;

// pNode = NULL;

//}

}//end while

//促使一个搜索线程从WaitForSingleObject返回,并退出循环

::SetEvent(pFinder->m_hDirEvent);

//判断此线程是否是最后一个结束循环的线程,如果是就通知主线程

if (::WaitForSingleObject(pFinder->m_hDirEvent,0) != WAIT_TIMEOUT)

{

::SetEvent(pFinder->m_hExitEvent);

}

return 1;

}

void main()

{

printf("start:n");

CRapidFinder* pFinder = new CRapidFinder(64);

CDirectoryNode* pNode = new CDirectoryNode;

char szPath[] = "c:";

char szFile[] = "config";

strcpy(pNode->szDir, szPath);

pFinder->m_listDir.AddHead(pNode);

strcpy(pFinder->m_szMatchName, szFile);

pFinder->m_nThreadCount = pFinder->m_nMaxThread;

//开始开启多线程

for (int i=0;i< pFinder->m_nMaxThread;i++)

{

::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FinderEntry, pFinder, 0, NULL);

}

//只有m_hExitEvent受信状态,主线程才恢复运行

::WaitForSingleObject(pFinder->m_hExitEvent,INFINITE);

printf("共找到%dn", pFinder->m_nResultCount);

//if (pNode != NULL) delete pNode;

if (pFinder != NULL) delete pFinder;

getchar();

return;

}

rapidfinder.h文件如下:

复制代码 代码如下:#include "_AFXTLS_.H"

struct CDirectoryNode: public CNoTrackObject

{

CDirectoryNode* pNext;

char szDir[MAX_PATH];

};

class CRapidFinder

{

public:

CRapidFinder(int nMaxThread); //构造函数

virtual ~CRapidFinder(); //析构函数

BOOL CheckFile(LPCTSTR lpszFileName); //检查lpszFileName是否符合查找条件

int m_nResultCount; //找到的结果数量

int m_nThreadCount; //当前的线程数量

CTypedSimpleList<CDirectoryNode*> m_listDir; //查找目录

CRITICAL_SECTION m_cs; //共享

const int m_nMaxThread; //最大线程数量

char m_szMatchName[MAX_PATH]; //要查找的名称

HANDLE m_hDirEvent; //添加新目录后置位

HANDLE m_hExitEvent; //所有线程退出时置位

};

下面这两个类就是实现了simplelist类和模板

_afxatl.cpp文件:

复制代码 代码如下:#include "_AFXTLS_.H"

void CSimpleList::AddHead(void* p)

{

*GetNextPtr(p) = m_pHead;

m_pHead = p;

}

BOOL CSimpleList::Remove(void* p)

{

if (p == NULL)

{

return FALSE;

}

BOOL bResult = FALSE;

if (p == m_pHead)

{

m_pHead = *GetNextPtr(m_pHead);

bResult = TRUE;

}

else

{

void* pTest = m_pHead;

while (pTest != NULL && *GetNextPtr(pTest) != p)

{

pTest = *GetNextPtr(pTest);

}

if (pTest != NULL)

{

*GetNextPtr(pTest) = *GetNextPtr(p);

bResult = TRUE;

}

}

return bResult;

}

void* CNoTrackObject::operator new(size_t nSize)

{

void* p = ::GlobalAlloc(GPTR, nSize);

return p;

}

void CNoTrackObject::operator delete(void* p)

{

if (p!=NULL)

{

::GlobalFree(p);

}

}

afxatl.h文件:

复制代码 代码如下:#ifndef _AFXTLS_H_H

#define _AFXTLS_H_H

#include <Windows.h>

class CSimpleList

{

public:

CSimpleList(int nNextOffset=0);

void Construct(int nNextOffset);

BOOL IsEmpty() const;

void AddHead(void* p);

void RemoveAll();

void* GetHead() const;

void* GetNext(void* p) const;

BOOL Remove(void* p);

//为实现接口所需要的成员

void* m_pHead;

int m_nNextOffset;

void** GetNextPtr(void* p) const;

};

//类的内联函数

inline CSimpleList::CSimpleList(int nNextOffset)

{m_pHead = NULL; m_nNextOffset = nNextOffset;}

inline void CSimpleList::Construct(int nNextOffset)

{m_nNextOffset = nNextOffset;}

inline BOOL CSimpleList::IsEmpty() const

{return m_pHead==NULL;}

inline void CSimpleList::RemoveAll()

{m_pHead=NULL;}

inline void* CSimpleList::GetHead() const

{return m_pHead;}

inline void* CSimpleList::GetNext(void* preElement) const

{

return *GetNextPtr(preElement);

}

inline void** CSimpleList::GetNextPtr(void* p) const

{

return (void**)((BYTE*)p + m_nNextOffset);

}

class CNoTrackObject

{

public:

void* operator new(size_t nSize);

void operator delete(void*);

virtual ~CNoTrackObject(){};

};

template<class TYPE>

class CTypedSimpleList:public CSimpleList

{

public:

CTypedSimpleList(int nNextOffset=0)

:CSimpleList(nNextOffset){}

void AddHead(TYPE p)

{

CSimpleList::AddHead((void*)p);

}

TYPE GetHead()

{

return (TYPE)CSimpleList::GetHead();

}

TYPE GetNext(TYPE p)

{

return (TYPE)CSimpleList::GetNext((void*)p);

}

BOOL Remove(TYPE p)

{

return CSimpleList::Remove(p);

}

operator TYPE()

{

return (TYPE)CSimpleList::GetHead();

}

};

#endif

希望本文所述对大家的C++程序设计有所帮助。

【C++实现多线程查找文件实例】相关文章:

linux c多线程编程实例代码

C/C++中退出线程的四种解决方法

线程池的原理与实现详解

C语言小程序 杨辉三角示例代码

C++中“#”号的使用技巧

显示任何进程加载的DLL文件的代码

用C语言实现单链表的各种操作(一)

C++实现:螺旋矩阵的实例代码

C++中strtok()函数的用法介绍

C语言实现逆波兰式实例

精品推荐
分类导航