热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

多线程搜索系统盘文件

说明:1.利用线程进行文件扫描。每遇到一个文件夹,创建一条线程进去搜索文件。(与递归类似)注意点:1.vector容器不安全。要设置临界区,不会多条线程同时对vector进行操作,实现同步。(原子

说明:
1.利用线程进行文件扫描。每遇到一个文件夹,创建一条线程进去搜索文件。(与递归类似)


注意点:
1.vector容器不安全。要设置临界区,不会多条线程同时对vector进行操作,实现同步。(原子操作)
2.具体步骤。
//临界区
CRITICAL_SECTION g_cs;
//初始化
InitializeCriticalSection(&g_cs);
//上锁
EnterCriticalSection(&g_cs);
//解锁
LeaveCriticalSection(&g_cs);
//释放
DeleteCriticalSection(&g_cs);

3.对线程进行计数。
加数
InterlockedAdd(&g_lThreadNum, 1);
减数
InterlockedAdd(&g_lThreadNum, -1);


4.设置多线程退出标识。HANDLE g_hExitEvent; //信号量。标记线程退出
因为是多线程进行操作,要保证线程全部退出后,主线程才退出,程序结束。

//创建事件消息
g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//如果全部线程退出,激活该信号量
SetEvent(&g_hExitEvent);

//只需等待信号量,即退出程序,不需要使用WaitForMultiObject(),会造成长时间等待、阻塞。
WaitForSingleObject(g_hExitEvent, INFINITE);

5.对容器进行释放
for (auto g_h_Threads: g_hThreads)
{
CloseHandle(g_h_Threads);
}

源代码:

#include "stdafx.h"
#include 
#include 
#include 
using namespace  std;
#include 
#include 

vector g_hThreads;    //存放线程的句柄
long g_lNum = 0;        //文件数目
long g_lFileNum=0;        //文件夹数目
long g_lThreadNum = 0;        //线程数目
HANDLE g_hExitEvent;        //标记线程退出
CRITICAL_SECTION g_cs;        //临界区

struct ThreadData
{
    wstring m_strBeginFileName;
    wstring m_strSearchFileName;
    wstring m_strFilte;
};

//文件路径标准化 "C:\\"
wstring MakeStdName(wstring &wstrFileName)
{
    if (wstrFileName.back() != '\\')
    {
        return (wstrFileName + L"\\");
    }
    else
        return  wstrFileName;

}


unsigned  _stdcall  FindFileThread(void * lParam)
{
    ThreadData *pData = (ThreadData *)lParam;
    WIN32_FIND_DATAW FileData = {0};
    HANDLE hFindFile = FindFirstFileW((MakeStdName(pData->m_strBeginFileName) + (pData->m_strFilte)).c_str(),&FileData);
    
    //可能打开文件失败,但是下面依然创建线程。
    if (hFindFile != INVALID_HANDLE_VALUE)
    {

        do
        {
            if (FileData.cFileName, L"." == 0)
                continue;
            if (FileData.cFileName, L".." == 0)
                continue;

            if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                ThreadData *pTempData = new ThreadData;
                pTempData->m_strBeginFileName =MakeStdName(pData->m_strBeginFileName) + FileData.cFileName;
                pTempData->m_strFilte = pData->m_strFilte;
                pTempData->m_strSearchFileName = pData->m_strSearchFileName;

                //上锁
                EnterCriticalSection(&g_cs);

                InterlockedAdd(&g_lThreadNum, 1);
                g_hThreads.push_back((HANDLE)_beginthreadex(NULL, 0, FindFileThread, pTempData, 0, NULL));
                
                
                //解锁
                LeaveCriticalSection(&g_cs);
            }
            else
            {
                if (wcsstr(FileData.cFileName, pData->m_strSearchFileName.c_str()) != NULL)
                {
                    printf("文件:%ls\r\n", (MakeStdName(pData->m_strBeginFileName) + FileData.cFileName).c_str());
                    InterlockedAdd(&g_lNum, 1);
                }
            }

        } while (FindNextFileW(hFindFile, &FileData));
    }
    delete pData;
    InterlockedAdd(&g_lThreadNum, -1);
    if (g_lThreadNum == 0)
    {
        SetEvent(&g_hExitEvent);
    }
    return g_lNum;
}


int _tmain(int argc, _TCHAR* argv[])
{

    DWORD dwBeginTime = GetTickCount();
    
    InitializeCriticalSection(&g_cs);
    
    g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    ThreadData *pTempData = new ThreadData;
    pTempData->m_strBeginFileName = L"C:\\";
    pTempData->m_strFilte = L"*.*";
    pTempData->m_strSearchFileName = L"ntdll";

    InterlockedAdd(&g_lThreadNum, 1);
    g_hThreads.push_back((HANDLE)_beginthreadex(NULL, 0, FindFileThread, pTempData, 0, NULL));

    WaitForSingleObject(g_hExitEvent, INFINITE);
    //for (auto g_h_Threads: g_hThreads)
    //{
    //    CloseHandle(g_h_Threads);
    //}
    DeleteCriticalSection(&g_cs);
    DWORD dwTime = GetTickCount() - dwBeginTime;

    _endthread();
    printf("文件夹个数:%d,ntdll文件个数: %d\r\n", g_lFileNum, g_lNum);
    printf("共用%d秒\r\n", dwTime / 1000);
    system("pause");
    return 0;
}

 


推荐阅读
  • 第14周实践项目(4)-验证平衡二叉树
    问题**Copyright(c)2015,烟台大学计算机学院*Allrightsreserved.*文件名称:test.cpp*作者:王敏*完成日 ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • Java毕业设计项目:“传情旧物”网站(含源码与数据库)
    本项目介绍了如何配置和运行“传情旧物”网站,包括所需的技术栈、环境配置以及具体的操作步骤。 ... [详细]
  • 最近遇到了一道关于哈夫曼树的编程题目,需要在下午之前完成。题目要求设计一个哈夫曼编码和解码系统,能够反复显示和处理多个项目,直到用户选择退出。希望各位大神能够提供帮助。 ... [详细]
  • PBO(PixelBufferObject),将像素数据存储在显存中。优点:1、快速的像素数据传递,它采用了一种叫DMA(DirectM ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • C语言编写线程池的简单实现方法
    2019独角兽企业重金招聘Python工程师标准好文章,一起分享——有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带 ... [详细]
  • Docker 环境下 MySQL 双主同步配置指南
    本文介绍了如何在 Docker 环境中配置 MySQL 的双主同步,包括目录结构的创建、配置文件的编写、容器的创建与设置以及最终的验证步骤。 ... [详细]
  • iOS 不定参数 详解 ... [详细]
  • python模块之正则
    re模块可以读懂你写的正则表达式根据你写的表达式去执行任务用re去操作正则正则表达式使用一些规则来检测一些字符串是否符合个人要求,从一段字符串中找到符合要求的内容。在 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
author-avatar
40740
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有