日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用完成端口监控文件目录的例子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

和完成例程比較。完成端口的效率更高。其主要原因是完成端口可以指定線程池。這么說吧,完成例程,每次只能由一個線程來監控IO 完成變化。但是完成端口,卻可以指定

一堆線程(想象一下一個人干活和一群人干活的區別)輪班的監控,即1號線程忙碌了,2號線程頂上去,如果2號也忙,3號頂上去!這樣,效率大大提高。

但是呢,線程的創建和銷毀是非常消耗時間的。所以,使用了線程池。另外線程涉及到CPU 上下文的切換問題。所以多線程的數量一般選擇2*CPU數量,但這是個經驗值

實際情況需要反復測試。

?

下面是BCB實現效果及源碼(參考資料 windows 核心編程 第10章,11章)

2014/12/23更新,增加臨界值保證cout的輸出不出現亂碼

2014/12/23更新,將ReadDirectoryChangesW 的緩沖區,移動到多線程中執行。

?

1 //--------------------------------------------------------------------------- 2 3 #include <vcl.h> 4 #include <iostream> 5 using namespace std; 6 #pragma hdrstop 7 8 //--------------------------------------------------------------------------- 9 10 #pragma argsused 11 12 HANDLE hMonitorDir = NULL; 13 HANDLE hCompletePort = NULL; 14 //因為cout 不是線程安全的,所以要用臨界值 15 CRITICAL_SECTION cs; 16 const DWORD CompleteKey = 1; 17 //讓完成端口處理線程池自己決定最多的線程并發數 18 const DWORD MaxThreadCount = 0; 19 DWORD dwByteReturn; 20 OVERLAPPED overlapped={0}; 21 DWORD dwError = 0; 22 int fileCount = 0; 23 24 25 //線程池 26 DWORD WINAPI ThreadProc(LPVOID lpParameter) 27 { 28 DWORD dwTranferBytes = 0; 29 DWORD dwKey = 0; 30 LPOVERLAPPED pOverLapped = &overlapped; 31 //捕獲文件信息的緩沖長度 32 DWORD dwBufLen 33 =2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR)); 34 //捕獲文件信息的緩沖buffer 35 FILE_NOTIFY_INFORMATION* Buffer 36 =(FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwBufLen); 37 38 //開始監控文件夾 39 if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE, 40 FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME, 41 &dwByteReturn,&overlapped,NULL)) 42 { 43 dwError = GetLastError(); 44 CloseHandle(hMonitorDir); 45 HeapFree(GetProcessHeap(),0,Buffer); 46 cout<<"監控文件夾失敗! "<<SysErrorMessage(dwError).c_str()<<endl; 47 return 0; 48 } 49 50 while(true) 51 { 52 53 //完成端口的關鍵所在 54 //和完成例程相比,完成端口的優勢是可以用線程池來監控IO,效率更高 55 BOOL blOk = GetQueuedCompletionStatus(hCompletePort, 56 &dwTranferBytes, 57 &dwKey, 58 &pOverLapped,INFINITE); 59 60 dwError = GetLastError(); 61 62 if(blOk && CompleteKey == dwKey) 63 { 64 //輸出線程編號 65 EnterCriticalSection( &cs ); 66 cout<<"線程號:"<<GetCurrentThreadId()<<endl; 67 LeaveCriticalSection( &cs ); 68 69 //捕獲到文件變化 70 FILE_NOTIFY_INFORMATION* notify = Buffer; 71 72 AnsiString fileName = 73 WideCharLenToString( 74 notify->FileName,notify->FileNameLength/2); 75 do 76 { 77 bool blNormal = true; 78 switch(notify->Action) 79 { 80 case FILE_ACTION_ADDED: 81 { 82 EnterCriticalSection( &cs ); 83 cout<<"增加了文件"<<fileName.c_str()<<endl; 84 LeaveCriticalSection( &cs ); 85 } 86 break; 87 case FILE_ACTION_REMOVED: 88 { 89 EnterCriticalSection( &cs ); 90 cout<<"刪除了文件"<<fileName.c_str()<<endl; 91 LeaveCriticalSection( &cs ); 92 } 93 break; 94 case FILE_ACTION_MODIFIED: 95 { 96 EnterCriticalSection( &cs ); 97 cout<<"修改了文件"<<fileName.c_str()<<endl; 98 LeaveCriticalSection( &cs ); 99 } 100 break; 101 case FILE_ACTION_RENAMED_OLD_NAME: 102 { 103 EnterCriticalSection( &cs ); 104 cout<<"被重名的文件"<<fileName.c_str()<<endl; 105 LeaveCriticalSection( &cs ); 106 } 107 break; 108 case FILE_ACTION_RENAMED_NEW_NAME: 109 { 110 EnterCriticalSection( &cs ); 111 cout<<"新命名的文件"<<fileName.c_str()<<endl; 112 LeaveCriticalSection( &cs ); 113 } 114 break; 115 default: //有可能已經溢出了! 116 blNormal = false; 117 break; 118 } 119 120 if(!blNormal) 121 { 122 break; 123 } 124 //將指針偏移offset個字節 125 notify = notify + notify->NextEntryOffset; 126 } 127 while(notify->NextEntryOffset>0); 128 129 if(!ReadDirectoryChangesW(hMonitorDir,Buffer,dwBufLen,TRUE, 130 FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME , 131 &dwByteReturn,&overlapped,NULL)) 132 { 133 dwError = GetLastError(); 134 CloseHandle(hMonitorDir); 135 CloseHandle(hCompletePort); 136 HeapFree(GetProcessHeap(),0,Buffer); 137 cout<<"監控文件夾失敗! "<<SysErrorMessage(dwError).c_str()<<endl; 138 break; 139 } 140 } 141 else 142 { 143 cout<<"完成端口異常! "<<SysErrorMessage(dwError).c_str()<<endl; 144 CloseHandle(hMonitorDir); 145 CloseHandle(hCompletePort); 146 HeapFree(GetProcessHeap(),0,Buffer); 147 break; 148 } 149 } 150 151 return 0; 152 } 153 154 int main(int argc, char* argv[]) 155 { 156 cout<<"開始監控程序目錄!...."<<endl; 157 AnsiString fileName = ExtractFileDir(Application->ExeName); 158 159 //打開目錄 160 hMonitorDir=CreateFile(fileName.c_str(), 161 FILE_LIST_DIRECTORY, //表明打開一個目錄 162 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 163 NULL, 164 OPEN_EXISTING, 165 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED表示異步模式 166 NULL); 167 dwError = GetLastError(); 168 if (INVALID_HANDLE_VALUE == hMonitorDir) 169 { 170 cout<<"打開文件目錄失敗! "<<SysErrorMessage(dwError).c_str()<<endl; 171 return 0; 172 } 173 //創建完成端口 174 hCompletePort = 175 CreateIoCompletionPort(hMonitorDir,NULL,CompleteKey,MaxThreadCount); 176 dwError = GetLastError(); 177 if(NULL == hCompletePort) 178 { 179 cout<<"創建完成端口失敗! "<<SysErrorMessage(dwError).c_str()<<endl; 180 CloseHandle(hMonitorDir); 181 return 0; 182 } 183 184 InitializeCriticalSection( &cs ); 185 //啟動線程池,在線程池中進行IO 完成監控 186 //如果是VISTA 以上級別的操作系統,建議使用 187 //TrySubmitThreadpoolCallback 188 //這里,我啟用五個工作線程,但實際上完成端口會自己調劑 189 for(int i = 0; i<5; i++) 190 { 191 QueueUserWorkItem(ThreadProc,NULL,0x00000000|0x00000010); 192 } 193 194 195 196 int i = 0; 197 cin>>i; 198 CloseHandle(hMonitorDir); 199 CloseHandle(hCompletePort); 200 return 0; 201 } 202 //---------------------------------------------------------------------------

?

轉載于:https://www.cnblogs.com/songr/p/4179298.html

總結

以上是生活随笔為你收集整理的使用完成端口监控文件目录的例子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。