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

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

代码如下:

//线程函数 
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; 
}

查找文件 的框架:

代码如下:

//从目录列表中成功取得了目录 
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] = '\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文件如下:

代码如下:

#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++程序设计有所帮助。

(0)

相关推荐

  • C++ 线程(串行 并行 同步 异步)详解

    C++  线程(串行 并行 同步 异步)详解 看了很多关于这类的文章,一直没有总结.不总结的话就会一直糊里糊涂,以下描述都是自己理解的非官方语言,不一定严谨,可当作参考. 首先,进程可理解成一个可执行文件的执行过程.在ios app上的话我们可以理解为我们的app的.ipa文件执行过程也即app运行过程.杀掉app进程就杀掉了这个app在系统里运行所占的内存. 线程:线程是进程的最小单位.一个进程里至少有一个主线程.就是那个main thread.非常简单的app可能只需要一个主线程即UI线程.

  • 从C++单例模式到线程安全详解

    先看一个最简单的教科书式单例模式: class CSingleton { public: static CSingleton* getInstance() { if (NULL == ps) {//tag1 ps = new CSingleton; } return ps; } private: CSingleton(){} CSingleton & operator=(const CSingleton &s); static CSingleton* ps; }; CSingleton*

  • C++封装线程类的实现方法

    本文实例讲述了C++封装线程类的实现方法.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: // 给主窗口的通知消息  #define WM_CUTTERSTART WM_USER + 100    // wParam == xxx  lParam==xxxx    /*  外面调用这个类时,只需要IsRunning() Startxxx(xxx) Suspendxxx()   Resumexxx() Stopxxx()  */    /*  m_bContinue在真正的工作代码Do

  • 老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)

    1 教科书里的单例模式 我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例. 上代码: class singleton { protected: singleton(){} private: static singleton* p; public: static singleton* instance()

  • linux下的C\C++多进程多线程编程实例详解

    linux下的C\C++多进程多线程编程实例详解 1.多进程编程 #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t child_pid; /* 创建一个子进程 */ child_pid = fork(); if(child_pid == 0) { printf("child pid\n"); exit(0); } else { print

  • c++实现简单的线程池

    这是对pthread线程的一个简单应用 1.      实现了线程池的概念,线程可以重复使用. 2.      对信号量,互斥锁等进行封装,业务处理函数中只需写和业务相关的代码. 3.      移植性好.如果想把这个线程池代码应用到自己的实现中去,只要写自己的业务处理函数和改写工作队列数据的处理方法就可以了. Sample代码主要包括一个主程序和两个线程实现类 ThreadTest.cpp:主程序 CThreadManager:线程管理Class,线程池的实现类 CThread:线程Class

  • C++实现一个线程安全的单例工厂实现代码

      C++实现一个线程安全的单例工厂实现代码 我们见到经常有人用 static 局部对象的方式实现了类似单例模式,最近发现一篇文章明确写明 编译器在处理  static局部变量的时候 并不是线程安全的 !!! http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx 于是实现了一个单例工厂  并且是线程安全的 #ifndef SINGLETONFACTORY_H #define SINGLETONFACTORY_H #in

  • C++使用CriticalSection实现线程同步实例

    本文实例讲述了C++使用CriticalSection实现线程同步的方法,在前文C++线程同步实例分析的基础上增加了四行代码,使用了四个函数: EnterCriticalSection ::DeleteCriticalSection ::EnterCriticalSection ::LeaveCriticalSection此时,打印出来的数字就相等了. 具体代码如下: #include "stdafx.h" #include <Windows.h> DWORD g_cnt1

  • C++程序中启动线程的方法

    C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥.锁和原子变量)的方法,我将试图为你介绍这个全新的线程库. 如果你要编译本文中的代码,你至少需要一个支持 C++11 的编译器,我使用的是 GCC 4.6.1,需要使用 -c++0x 或者 -c++11 参数来启用 C++11 的支持. 启动线程 在 C++11 中启动一个线程是非常简单的,你可以使用 std:thread 来创建一个线程实例,创建完会自动启动,只需要给它传递一个要执行函数的指针即可,请看下面这个 Hel

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

    主要是多线程的互斥 文件 的查找 多线程互斥的框架 复制代码 代码如下: //线程函数  UINT FinderEntry(LPVOID lpParam)  {      //CRapidFinder通过参数传递进来       CRapidFinder* pFinder = (CRapidFinder*)lpParam;      CDirectoryNode* pNode = NULL;      BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活   

  • Java多线程下载文件实例详解

    本文实例为大家分享了Java多线程下载文件的具体代码,供大家参考,具体内容如下 import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MulThreadDownload { public static void main(String[] args)

  • 对Python多线程读写文件加锁的实例详解

    Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对文件的读写操作.在管理多个线程对同一文件的读写操作时,就少不了文件锁了. 使用fcntl 在linux下,python的标准库有现成的文件锁,来自于fcntl模块.这个模块提供了unix系统fcntl()和ioctl()的接口. 对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数. 其中,参数 fd 表示文件描述符:参数 operation 指定要进行的锁操作,该参数的取值有如

  • 对Python 文件夹遍历和文件查找的实例讲解

    实例如下所示: # -*- coding: utf-8 -*- #to find where use the table on xxxxx xxxxxx production env ''' 在项目中我们元数据管理的不是很好,如果先知道一张表在哪里用过,就需要写个程序去遍历下 ''' import os import os.path rootdir = "C:\\Users\\IBM_ADMIN\\IBM\\rationalsdp\\workspace"# # 指明被遍历的文件夹 qu

  • Java编程利用socket多线程访问服务器文件代码示例

    这篇文章将向大家展示Java编程利用socket多线程访问服务器文件代码示例,如果您想先了解Java多线程socket编程的基础知识,可以看下这篇文章:Java多线程编程实现socket通信示例代码. 接下来进入正文,我们看看利用socket多线程访问服务器代码: ServerMain.java package com.ysk.webServer; import java.io.File; import java.io.IOException; import java.net.ServerSoc

  • Android实现多线程下载文件的方法

    本文实例讲述了Android实现多线程下载文件的方法.分享给大家供大家参考.具体如下: 多线程下载大概思路就是通过Range 属性实现文件分段,然后用RandomAccessFile 来读写文件,最终合并为一个文件 首先看下效果图: 创建工程 ThreadDemo 首先布局文件 threaddemo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo

  • Python3实现从指定路径查找文件的方法

    本文实例讲述了Python3实现从指定路径查找文件的方法.分享给大家供大家参考.具体实现方法如下: 这里给定一个搜索路径,根据这个路径请求和请求的文件名,找到第一个符合要求的文件 import os def search_file(file_name, search_path, pathsep = os.pathsep): for path in search_path.split(pathsep): candidate = os.path.join(path, file_name) if os

  • Python多线程下载文件的方法

    本文实例讲述了Python多线程下载文件的方法.分享给大家供大家参考.具体实现方法如下: import httplib import urllib2 import time from threading import Thread from Queue import Queue from time import sleep proxy = 'your proxy'; opener = urllib2.build_opener( urllib2.ProxyHandler({'http':proxy

  • jQuery读取本地的json文件(实例讲解)

    最近写项目需要读取本地的json文件,然后悲催的发现前端新手的我居然不会,查查找找发现这东西并不难,但是应该是比较常用的,毕竟json太好用了! 我是直接用的 jquery 实现的,但是 Ajax 也可以,不过我用的Ajax的简约版 $.getJSON(url,function); 代码如下: function getScenemapData(){ var jsondata={}; $.getJSON("../server/php/files/scenedesc.json", func

  • C#实现多线程下载文件的方法

    本文实例讲述了C#实现多线程下载文件的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; using System.Net; namespace WfpApp { public class MultiDownload { #region 变量 pri

随机推荐