2013-12-17 75 views
1

我設法同步使用ReadDirectoryChangesW,但是當我嘗試使用完成端口時,ReadDirectoryChangesW始終返回ERROR_INVALID_PARAMETER。我想在我的代碼中應該有一些明顯的錯誤,但我無法想象它。異步ReadDirectoryChangesW失敗,ERROR_INVALID_PARAMETER

我的代碼是基於How to use ReadDirectoryChangesW() method with completion routine?

const wchar_t *directory = L"X:\\X"; 
    HANDLE h = CreateFile(
     directory, 
     FILE_LIST_DIRECTORY, 
     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
     NULL, OPEN_EXISTING, 
     FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL); 

    if (h==INVALID_HANDLE_VALUE) return; 

    HANDLE p = CreateIoCompletionPort(h,0,0,1); 
    if (p==NULL) {CloseHandle(h); return;} 

    DWORD *buffer =new DWORD[4096]; 
    DWORD bytesReturned; 

    DWORD notifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME 
         | FILE_NOTIFY_CHANGE_DIR_NAME 
         | FILE_NOTIFY_CHANGE_SIZE 
         | FILE_NOTIFY_CHANGE_LAST_WRITE; 

    while (true) { 

     OVERLAPPED overlapped; 
     memset(&overlapped,0,sizeof(overlapped)); 

     BOOL success = ReadDirectoryChangesW(h, 
      &buffer[0],    
      4096*sizeof(DWORD), 
      FALSE, notifyFilter, 
      NULL, //&bytesReturned, 
      &overlapped,myFileIOCompletionRoutine); 

     if (!success) {  
      //always ERROR_INVALID_PARAMETER  
      CloseHandle(h); 
      CloseHandle(p); 
      return; 
     }  
    } 
+0

您沒有顯示notifyFilter和myFileIOCompletionRoutine定義。 –

+1

如果失敗,CreateIoCompletionPort返回NULL,您的測試不正確。也許CreateIoCompletionPort失敗? –

+0

@AlexFarber,感謝您指出它,但CreateIoCompletionPort返回一個有效的句柄。 – Javier

回答

1

漢斯·帕桑特好心提醒,the documentation已經說完成例程不得使用如果目錄關聯到一個完成端口。在這種情況下,我通過等待完成端口來解決問題,即ReadDirectoryChangesW(...,&overlapped,0);

完整的代碼如下。

while (true) { 
    OVERLAPPED overlapped; 
    memset(&overlapped,0,sizeof(overlapped)); 
    BOOL success = ReadDirectoryChangesW(h, 
      &buffer[0], 
      4096*sizeof(DWORD), 
      FALSE, notifyFilter, 0, &overlapped,0); 

    if (!success) { 
     if (GetLastError()==ERROR_INVALID_HANDLE) { 
     //asynchronously closed by cancel 
     CloseHandle(p); //close completion port 
     return 0; 
     } else { 
     CloseHandle(h); //close directory handle 
     CloseHandle(p); //close completion port 
     return 1; 
     } 
    } 

    DWORD di; 
    LPOVERLAPPED lpOverlapped; 
    if (!GetQueuedCompletionStatus(p,&bytesReturned,&di,&lpOverlapped,1000)) { 
     int ret; 
     if (GetLastError()==WAIT_TIMEOUT) { 
      if (GetFileAttributes(directory)!=INVALID_FILE_ATTRIBUTES) { 
       continue; //timeout 
      } else { 
       //directory has been deleted or renamed 
       ret=0; 
      } 
     } else { 
      //other failure 
      ret=1; 
     } 
     CloseHandle(h); //close directory handle 
     CloseHandle(p); //close completion port 
     return ret; 
    } 

    char* ptr = (char*)&buffer[0]; 
    char* end = ptr+bytesReturned; 
    while (ptr<end) { 
     FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*) ptr; 
     //process FILE_NOTIFY_INFORMATION 
     ptr+=info->NextEntryOffset; 
     if (!info->NextEntryOffset) break; 
    } 
    }