Windows程序设计第二版中多功能文件搜索器?

hyz23je 2011-11-28 03:53:59

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;
}


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);
printf(" %s \n", fileData.cFileName);
}
}
}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;
}

问题一
::SetEvent(pFinder->m_hDirEvent); //是设置成为受信,但不明白它设置对应的是那个WaitForSingleObject呢?

if(pNode->szDir[strlen(pNode->szDir)-1] != '\\') //这里的判断为什么会是假的?里面减1有意义何在?
strcat(pNode->szDir, "\\");


strncpy(p->szDir, pNode->szDir, strlen(pNode->szDir)-3); //里面为什么要减3呢

就这三个问题!那位朋友帮忙解释下!




...全文
56 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
hyz23je 2011-11-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 visualeleven 的回复:]
1. 看你的传递给线程的那个结构体变量里的EVENT成员是哪个
[/Quote]

不太明白!
hyz23je 2011-11-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 oyljerry 的回复:]
1. 查对应的event哪个在wait
2,减一获取字符串最后一个字符,然后判断是否为\结尾
[/Quote]

查过了!有两个!所以不知道它在哪一个上?
你回答的“减一获取字符串最后一个字符,然后判断是否为\结尾
”能再解释清楚一点吗?
Eleven 2011-11-28
  • 打赏
  • 举报
回复
后面两个Debug下调试一下看看具体的数据就知道为什么了
Eleven 2011-11-28
  • 打赏
  • 举报
回复
1. 看你的传递给线程的那个结构体变量里的EVENT成员是哪个
oyljerry 2011-11-28
  • 打赏
  • 举报
回复
1. 查对应的event哪个在wait
2,减一获取字符串最后一个字符,然后判断是否为\结尾
hyz23je 2011-11-28
  • 打赏
  • 举报
回复
自己顶个!
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;
}


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);
printf(" %s \n", fileData.cFileName);
}
}
}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;
}

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧