首页 > 代码库 > 使用完成端口监控文件目录的例子
使用完成端口监控文件目录的例子
和完成例程比较。完成端口的效率更高。其主要原因是完成端口可以指定线程池。
下面是BCB实现效果及源码(参考资料 windows 核心编程 第10章,11章)
//---------------------------------------------------------------------------#include <vcl.h>#include <iostream>using namespace std;#pragma hdrstop//---------------------------------------------------------------------------#pragma argsusedHANDLE 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 =http://www.mamicode.com/= 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;}//---------------------------------------------------------------------------
使用完成端口监控文件目录的例子
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。