【问题标题】:Listing Files using Multithreading with windows API in c++在 C++ 中使用多线程和 Windows API 列出文件
【发布时间】:2014-01-20 10:34:19
【问题描述】:

我编写了一个将目录作为输入并在其中输出文件列表的代码。我在单线程中实现了它。为了使用多线程实现该怎么做?给我逻辑或代码。

平台:Windows API:Windows.h 语言:c++

    #include <iostream>
    #include <Windows.h>
    #include <queue>
    #include <TlHelp32.h>
    #include <string>
    #include <vector>

    using namespace std;
    #define MAX_THREADS 1

    int Files = 0;
    vector<string>files;


    vector<string> ListContents(string path,vector<string>&files)
    {
        HANDLE hfind = INVALID_HANDLE_VALUE;
        WIN32_FIND_DATAA ffd;
        string spec;
        wstring ws;
        deque<string> directories;

        directories.push_back(path);
        files.clear();

        while(!directories.empty())
        {
            path = directories.back();
            spec = path + "\\" + "*";
            directories.pop_back();

            std::wstring wspec( spec.begin(),spec.end());
            ws = wspec;

            hfind = FindFirstFileA(spec.c_str(),&ffd);
            if(hfind == INVALID_HANDLE_VALUE)
                continue;
                //return false;

            do
            {
                if(strcmp(ffd.cFileName,".") && strcmp(ffd.cFileName,".."))
                {
                    if(ffd.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
                    {
                        directories.push_back(path + "\\" + ffd.cFileName );
                    }
                    else
                    {
                        //cout<<"Current File is "<<ffd.cFileName<<endl;
                        files.push_back(path + "\\" + ffd.cFileName);
                        Files++;
                    }
                }
            }while(FindNextFileA(hfind,&ffd)!=0);
            if (GetLastError() != ERROR_NO_MORE_FILES) {
                FindClose(hfind);
                ExitProcess(4);
                //return false;
            }

            FindClose(hfind);
            hfind = INVALID_HANDLE_VALUE;
        }

        //return true;
        return files;
    }
    void display(vector<string>&files)
    {
        vector<string>::iterator iter = files.begin();
            if(files.size()!=0)
                do
                {
                    cout<<*iter<<endl;
                    *iter++;
                }while(iter!=files.end());

    }
    DWORD WINAPI MyThread1(LPVOID s)
    {
        char* ss = (char*)s;
        string path(ss);
        //vector<string> files;
        files = ListContents(path,files);
        //display(files);
        return 0;
    }
    int main(int argc,char *argv[])
    {
        DWORD threadid;
        int newent = 0;
        int newex = 0;
        FILETIME creation,exit,kernel,user;
        SYSTEMTIME st1,st2;
        THREADENTRY32 entry;
        char szEntrytime[255],szExittime[255];

        //vector<string> files;
         Sem = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
        for(int i= 0;i<MAX_THREADS;i++)
    {
        hthread[i] = CreateThread(NULL,0,List,NULL,0,&threadid);
         if( hthread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return 1;
        }
    }

        HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);

        if(hthread)
        {
            WaitForMultipleObjects(MAX_THREADS,&hthread,TRUE,INFINITE);

             if(GetThreadTimes(hthread,&creation,&exit,&kernel,&user)==0)
             {
                 cout<<"can't able to get thrad timings";
                 ExitProcess(3);
             }
             else
             {
                 GetThreadTimes(hthread,&creation,&exit,&kernel,&user);
                 FileTimeToLocalFileTime(&creation,&creation);
                 FileTimeToLocalFileTime(&exit,&exit);
                 FileTimeToSystemTime(&creation,&st1);
                 FileTimeToSystemTime(&exit,&st2);
             }
        }

        GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st1, NULL, szEntrytime, 255 );
        GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st2, NULL, szExittime, 255 );

        printf( "Thread Entry Time %s\n", szEntrytime );
        printf( "Thread Exit Time %s\n", szExittime );


        //files = ListContents(argv[1],files);

        cout<<" No of Files  "<<Files <<endl ;
        CloseHandle(hthread);

        display(files);


        /*if(ListContents(argv[1],files))
        {

        }*/
        system("pause");
        return 0;
    }

【问题讨论】:

  • 更好的方法是将boost::filesystem::directory_iterator 和英特尔的tbb::parallel_for_each 结合起来。
  • 我试过了,但是 boost 文件系统是预先包含在 linux 中的。对于 Windows,我需要越来越多的依赖文件。我需要一个解决方案来在 windows 平台上实现它,而不是跨平台。
  • 祝你好运; windows API 应被视为不应直接调用的低级 API。也及时 boost.filesystem 将成为 std.filesystem。您可以使用 MS 并行模式库而不是 intel tbb。

标签: c++ multithreading winapi


【解决方案1】:

我想到的第一个方法是使用producer/consumer pattern,您的消费者也是生产者。这个想法是将单个目录中的文件列表(非递归)映射到任务。这些任务可以并行处理。

例如最初你有一个任务 - 处理你给定的目录。当您找到一个子目录时,您将其添加到directories 向量中,因此等待工作的another thread from your pool 可以执行此任务和处理。因此,您需要将directories 转换为生产者/消费者队列并创建线程池来处理此队列。每次您找到一个子目录时,都像现在一样添加到该队列中。

唯一的问题是检测您何时完成工作。您可以使用诸如计数器之类的东西来等待没有工作要做的线程。当该计数器达到池中的线程数时 - 将终止项目发布到队列中,每个线程一个项目,这清楚地表明消耗该项目的线程应该终止。

【讨论】:

  • 非常感谢安迪..但是当我通过这个时,我对如何将我的目录(双端队列)结构更改为生产者/消费者结构有疑问。我是 c++ 中的多线程新手。你能不能用代码详细说明?
  • "以下代码实现了一个生产者/消费者队列。队列表示为有界循环缓冲区,并受临界区保护。代码使用两个条件变量:一个由生产者使用(BufferNotFull ) 和消费者使用的一个 (BufferNotEmpty)。": msdn.microsoft.com/en-us/library/windows/desktop/…
  • 我尝试了你告诉的模式...我从两个线程调用函数 ListContents() 但如何将队列作为线程池???
  • 我会尝试更详细地解释它。首先,找个好的线程池实现,或者用(这个)[stackoverflow.com/questions/12215395/…和Boost.Thread。作为最后的手段,根本不要打扰线程池,只需创建具有相同线程功能的线程束(任意数量,最初在 2 个线程上测试)。这个函数应该从你的生产者/消费者队列中获取循环项目并传递给你的函数(为多线程处理而修改),直到找到特殊项目(null?)。
  • 非常感谢您提供的建议..我在这里放弃我的算法,如果有任何错误请纠正我
【解决方案2】:

全局队列(由驱动器/目录中的文件夹组成)本地队列(子文件夹的线程函数内)

    while(true)
{
    lock()
    if( Global q empty)
        unlock
        break
    else
       get first folder from global q
      put it in local q
     unlock

    while(local q not empty)
        take first folder from local q
        process it
        if( folder)
           put it in local q
        else
         put it in vector ( othr purpose)
}

【讨论】:

    猜你喜欢
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    相关资源
    最近更新 更多