- UID
- 247
- 精华
- 积分
- 99
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
本帖最后由 Fluray 于 2014-5-5 08:23 编辑
新建一个控制台,要支持MFC。
只用了MFC一个函数AfxBeginThread,其余的全是win API。线程函数修改自《windows程序设计 第2版》 王艳平 张铮 编著
- // 多线程文件搜索.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <afxwin.h>
- #include <process.h>
- #include <iostream>
- #include <stddef.h>
- #define BUFSIZE 1024
- using namespace std;
- //int g_FileName=0;
- struct CDirectoryNode : public CNoTrackObject
- {
- CDirectoryNode* pNext; // CTypedSimpleList类模板要使用此成员
- char szDir[MAX_PATH]; // 要查找的目录
- };
- class CRapidFinder
- {
- public:
- CRapidFinder(int nMaxThread);
- virtual ~CRapidFinder();
- BOOL CheckFile(LPCTSTR 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; // 向m_listDir中添加新的目录后置位(受信)
- HANDLE m_hExitEvent; // 各搜索线程将要退出时置位(受信)
- };
- // m_nMaxThread成员是一个const类型的变量,必须使用成员初始化列表来初始化它的值
- CRapidFinder::CRapidFinder(int nMaxThread) : m_nMaxThread(nMaxThread)
- {
- m_nResultCount = 0;
- m_nThreadCount = 0;
- m_szMatchName[0] = '\0';
- m_listDir.Construct(offsetof(CDirectoryNode, pNext));
- m_hDirEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
- m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
- ::InitializeCriticalSection(&m_cs);
- }
- CRapidFinder::~CRapidFinder()
- {
- ::CloseHandle(m_hDirEvent);
- ::CloseHandle(m_hExitEvent);
- ::DeleteCriticalSection(&m_cs);
- }
- //包含此文件名的文件都会被查找到
- //BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName)
- //{
- // char string[MAX_PATH];
- // char strSearch[MAX_PATH];
- // strcpy(string, lpszFileName);
- // strcpy(strSearch, m_szMatchName);
- //
- // // 将字符串string和strSearch中的字符全部转化成大写
- // _strupr(string);
- // _strupr(strSearch);
- //
- // // 找出字符串strSearch在字符串string中第一次出现的位置
- // // 如果string中不包含strSearch,strstr函数返回NULL
- // if(strstr(string, strSearch) != NULL)
- // return TRUE;
- //
- // return FALSE;
- //}
- //必须是相同问文件名(大小写可以不同)
- BOOL CRapidFinder::CheckFile(LPCTSTR lpszFileName)
- {
- char string[MAX_PATH];
- char strSearch[MAX_PATH];
- strcpy(string, lpszFileName);
- strcpy(strSearch, m_szMatchName);
- // 将字符串string和strSearch中的字符全部转化成大写
- _strupr(string);
- _strupr(strSearch);
- //如果两个文件名称相同
- if(strcmp(string, strSearch) == 0)
- return TRUE;
- return FALSE;
- }
- UINT FinderEntry(LPVOID lpParam)
- {
- CRapidFinder* pFinder = (CRapidFinder*)lpParam;
- CDirectoryNode* pNode = NULL; // 从m_listDir中取出的节点
- BOOL bActive = TRUE; // 指示当前线程的状态
- // 循环处理m_listDir列表中的目录
- while(1)
- {
- // 从m_listDir列表中取出一个新的目录
- ::EnterCriticalSection(&pFinder->m_cs);
- if(pFinder->m_listDir.IsEmpty())
- {
- bActive = FALSE;
- }
- else
- {
- pNode = pFinder->m_listDir.GetHead();
- pFinder->m_listDir.Remove(pNode);
- }
- ::LeaveCriticalSection(&pFinder->m_cs);
- // m_listDir为空的话就试图在m_hDirEvent事件上等待
- if(!bActive)
- {
- // 准备进入等待状态
- ::EnterCriticalSection(&pFinder->m_cs);
- pFinder->m_nThreadCount--;
- if(pFinder->m_nThreadCount == 0) // 查看是否已经查找完毕
- {
- ::LeaveCriticalSection(&pFinder->m_cs);
- break;
- }
- ::LeaveCriticalSection(&pFinder->m_cs);
- // 进入等待状态
- ResetEvent(pFinder->m_hDirEvent);
- ::WaitForSingleObject(pFinder->m_hDirEvent, INFINITE);
- // 变成活动线程后进入下一次循环
- ::EnterCriticalSection(&pFinder->m_cs);
- pFinder->m_nThreadCount++;
- ::LeaveCriticalSection(&pFinder->m_cs);
- bActive = TRUE;
- continue;
- }
-
-
- // 在pNode指向的目录中查找文件
- WIN32_FIND_DATA fileData;
- HANDLE hFindFile;
- // 设置成X:\XXXX\*.*的格式
- 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);
- strcat(p->szDir, fileData.cFileName);
- // 添加到列表中
- ::EnterCriticalSection(&pFinder->m_cs);
- pFinder->m_listDir.AddHead(p);
- ::LeaveCriticalSection(&pFinder->m_cs);
- // 促使一个“非活动线程”变成“活动线程”
- ::SetEvent(pFinder->m_hDirEvent);
- }
- else
- {
- // 检查搜索到的文件
- if(pFinder->CheckFile(fileData.cFileName))
- {
- ::EnterCriticalSection(&pFinder->m_cs);
- ::InterlockedIncrement((long*)&pFinder->m_nResultCount);
- ::LeaveCriticalSection(&pFinder->m_cs);
- char FileName[256];
- int i;
- for (i=strlen(pNode->szDir)-4;i>=0;i--)
- FileName[i]=pNode->szDir[i];
- FileName[strlen(pNode->szDir)-3]='\0';
- strcat(FileName, fileData.cFileName);
- printf("%s \n",FileName);
-
- }
- }
- }while(::FindNextFile(hFindFile, &fileData));
- }
- // 此节点保存的目录已经搜索完毕,释放内存空间,进入下次循环
- delete pNode;
- pNode = NULL;
- }
- // 促使一个搜索线程从WaitForSingleObject函数返回,并退出循环
- ::SetEvent(pFinder->m_hDirEvent);
- // 判断此线程是否是最后一个结束循环的线程,如果是就通知主线程
- if(::WaitForSingleObject(pFinder->m_hDirEvent, 0) != WAIT_TIMEOUT)
- // 如果此时pFinder->m_hDirEvent所对应的事件对象为受信状态,
- // WaitForSingleObject函数的返回值将是WAIT_OBJECT_0
- {
- // 通知主线程最后一个搜索线程即将退出,文件搜索完毕
- ::SetEvent(pFinder->m_hExitEvent);
-
- }
- return 0;
- }
- void main()
- {
- char szFile[256];
- char szPath[256] ;
- char szLogicalDriveStrings[BUFSIZE];
- DWORD iLength;
- int iSub;
- int count=0;
- clock_t start,end;//程序运行的起始和结束时间
- float costtime;//程序耗时
- printf("请输入想查找的文件名:");
- scanf("%s",szFile);
- ZeroMemory(szLogicalDriveStrings, BUFSIZE);
- iLength = GetLogicalDriveStringsA(BUFSIZE-1, szLogicalDriveStrings);
- start=clock();//开始计时
- for(iSub=0; iSub<iLength; iSub+=4)
- {
- CRapidFinder* pFinder = new CRapidFinder(64);
- CDirectoryNode* pNode = new CDirectoryNode;
- //如果不是固定磁盘驱动器:本地硬盘或移动硬盘,忽略
- if(GetDriveType(szLogicalDriveStrings+iSub)!=3)
- continue;
- /*printf("%s ", szLogicalDriveStrings+iSub);*/
- // 设置参数信息
- strcpy(pNode->szDir, szLogicalDriveStrings+iSub);
- 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++)
- {
- AfxBeginThread(FinderEntry, pFinder);
- }
- ::WaitForSingleObject(pFinder->m_hExitEvent, INFINITE);
- // 打印出结果
- /*printf("%s 中最终查找到的文件的个数为:%d \n",szLogicalDriveStrings+iSub, pFinder->m_nResultCount);*/
- count=count+pFinder->m_nResultCount;
- delete pFinder;
- }
- end=clock();//计时结束
- costtime= (float)(end - start) / CLOCKS_PER_SEC; //转换时间格式
- /*ShellExecute(NULL,"open",g_FileName,NULL,NULL,SW_SHOWNORMAL);*/
- printf("使用64个线程全盘搜索文件%s,一共搜索到%d个,用时%.5f s",szFile,count,costtime);
- system("pause");
- }
复制代码
|
-
|