源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

C++实现多线程查找文件实例

  • 时间:2020-10-27 21:15 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:C++实现多线程查找文件实例
主要是多线程的互斥 文件 的查找 多线程互斥的框架
[u]复制代码[/u] 代码如下:
//线程函数  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 style="white-space:pre">      </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;  }
查找文件 的框架:
[u]复制代码[/u] 代码如下:
//从目录列表中成功取得了目录  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:
[u]复制代码[/u] 代码如下:
#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] = '\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:%s\n", 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("共找到%d\n", pFinder->m_nResultCount);      //if (pNode != NULL) delete pNode;      if (pFinder != NULL) delete pFinder;        getchar();      return;  }
rapidfinder.h文件如下:
[u]复制代码[/u] 代码如下:
#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文件:
[u]复制代码[/u] 代码如下:
#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文件:
[u]复制代码[/u] 代码如下:
#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++程序设计有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部