首页 > 其他 > 详细

使用完成端口监控文件目录的例子

时间:2014-12-23 01:27:22      阅读:652      评论:0      收藏:0      [点我收藏+]

和完成例程比较。完成端口的效率更高。其主要原因是完成端口可以指定线程池。

下面是BCB实现效果及源码(参考资料 windows 核心编程 第10章,11章)

技术分享

 

//---------------------------------------------------------------------------

#include <vcl.h>
#include <iostream>
using namespace std;
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

HANDLE hMonitorDir = NULL;
HANDLE hCompletePort = NULL;
const DWORD CompleteKey = 1;
//让完成端口处理线程池自己决定最多的线程并发数
const DWORD MaxThreadCount = 0;
DWORD dwByteReturn;
OVERLAPPED overlapped={0};
DWORD dwError = 0;
int fileCount = 0;


//线程池
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    DWORD dwTranferBytes = 0;
    DWORD dwKey = 0;
    LPOVERLAPPED pOverLapped = &overlapped;
    //捕获文件信息的缓冲长度
    DWORD dwBufLen
        =2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR));
    //捕获文件信息的缓冲buffer
    FILE_NOTIFY_INFORMATION* Buffer
        =(FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufLen);

    while(true)
    {
        //完成端口的关键所在
        //和完成例程相比,完成端口的优势是可以用线程池来监控IO,效率更高
        BOOL blOk = GetQueuedCompletionStatus(hCompletePort,
                                &dwTranferBytes,
                                &dwKey,
                                &pOverLapped,INFINITE);

        dwError = GetLastError();
        //输出线程编号
        cout<<"线程号:"<<GetCurrentThreadId()<<endl;
        
        if(blOk && CompleteKey == dwKey)
        {
            //捕获到文件变化
            FILE_NOTIFY_INFORMATION* notify = Buffer;

            AnsiString fileName =
                    WideCharLenToString(
                        notify->FileName,notify->FileNameLength/2);
            do
            {
                bool blNormal = true;
                switch(notify->Action)
                {
                case FILE_ACTION_ADDED:
                    {
                        cout<<"增加了文件"<<fileName.c_str()<<endl;
                    }
                    break;
                case FILE_ACTION_REMOVED:
                    {
                        cout<<"删除了文件"<<fileName.c_str()<<endl;
                    }
                    break;
                case FILE_ACTION_MODIFIED:
                    {
                        cout<<"修改了文件"<<fileName.c_str()<<endl;
                    }
                    break;
                case FILE_ACTION_RENAMED_OLD_NAME:
                    {
                        cout<<"被重名的文件"<<fileName.c_str()<<endl;
                    }
                    break;
                case FILE_ACTION_RENAMED_NEW_NAME:
                    {
                        cout<<"新命名的文件"<<fileName.c_str()<<endl;
                    }
                    break;
                default:   //有可能已经溢出了!
                    blNormal = false;
                    break;
                }

                if(!blNormal)
                {
                    break;
                }
                //将指针偏移offset个字节
                notify =  notify + notify->NextEntryOffset;
            }
            while(notify->NextEntryOffset>0);

            if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE,
                    FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME ,
                    &dwByteReturn,&overlapped,NULL))
            {
                dwError = GetLastError();
                CloseHandle(hMonitorDir);
                CloseHandle(hCompletePort);
                HeapFree(GetProcessHeap(),0,Buffer);
                cout<<"监控文件夹失败! "<<SysErrorMessage(dwError).c_str()<<endl;
                break;
            }
        }
        else
        {
            cout<<"完成端口异常! "<<SysErrorMessage(dwError).c_str()<<endl;
            CloseHandle(hMonitorDir);
            CloseHandle(hCompletePort);
            HeapFree(GetProcessHeap(),0,Buffer);
            break;
        }
    }

    return 0;
}

int main(int argc, char* argv[])
{
    cout<<"开始监控程序目录!...."<<endl;
    AnsiString fileName = "G:\\unireport20\\Report\\Out\\ImageUpload\\2014";//ExtractFileDir(Application->ExeName);

    //打开目录
    hMonitorDir=CreateFile(fileName.c_str(),
        FILE_LIST_DIRECTORY,  //表明打开一个目录
        FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED表示异步模式
        NULL);
    dwError = GetLastError();
    if (INVALID_HANDLE_VALUE == hMonitorDir)
    {
        cout<<"打开文件目录失败! "<<SysErrorMessage(dwError).c_str()<<endl;
        return 0;
    }
    //创建完成端口
    hCompletePort =
        CreateIoCompletionPort(hMonitorDir,NULL,CompleteKey,MaxThreadCount);
    dwError = GetLastError();
    if(NULL == hCompletePort)
    {
        cout<<"创建完成端口失败! "<<SysErrorMessage(dwError).c_str()<<endl;
        CloseHandle(hMonitorDir);
        return 0;
    }

    //捕获文件信息的缓冲长度
    DWORD dwBufLen
        =2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR));
    //捕获文件信息的缓冲buffer
    FILE_NOTIFY_INFORMATION* Buffer
        =(FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufLen);


    //开始监控文件夹
    if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE,
            FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME,
            &dwByteReturn,&overlapped,NULL))
    {
        dwError = GetLastError();
        CloseHandle(hMonitorDir);
        HeapFree(GetProcessHeap(),0,Buffer);
        cout<<"监控文件夹失败! "<<SysErrorMessage(dwError).c_str()<<endl;
    }
    
    //启动线程池,在线程池中进行IO 完成监控
    //如果是VISTA 以上级别的操作系统,建议使用
    //TrySubmitThreadpoolCallback
    //这里,我启用五个工作线程,但实际上完成端口会自己调剂
    for(int i = 0; i<5; i++)
    {
        QueueUserWorkItem(ThreadProc,NULL,0x00000000|0x00000010);
    }

    int i = 0;
    cin>>i;
    CloseHandle(hMonitorDir);
    CloseHandle(hCompletePort);
    HeapFree(GetProcessHeap(),0,Buffer);
    return 0;
}
//---------------------------------------------------------------------------

 

使用完成端口监控文件目录的例子

原文:http://www.cnblogs.com/songr/p/4179298.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!