2009-11-17 26 views
5

Tôi đang xem một thư mục bằng cách gọi ReadDirectoryChangesW đồng bộ. Khi có tệp mới, tôi cố gắng truy cập ngay lập tức với CreateFile với GENERIC_READFILE_SHARE_READ, nhưng điều này mang lại cho tôi ERROR_SHARING_VIOLATION. Quá trình đưa tập tin vào thư mục đã xem không hoàn thành bằng văn bản vào lúc tôi cố đọc nó.Chờ cho đến khi có tệp để đọc với Win32

Có cách nào đáng tin cậy để chờ cho đến khi tệp có sẵn để đọc không? Tôi có thể đặt phương pháp vào một vòng lặp như một bên dưới, nhưng tôi hy vọng có một cách tốt hơn.

while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) 
     Sleep (500); 
    else 
     break; // some other error occurred 
} 

if (hFile == INVALID_HANDLE_VALUE) 
{ 
    // deal with other error 
    return 0; 
} 

ReadFile (...); 
+0

Tôi cho rằng đây là C++? Nếu nó là C#, có một đối tượng SystemFileWatcher trong BCL mà bạn có thể sử dụng. –

+0

Win32 == C API, tôi sẽ gắn thẻ lại. – dreamlax

Trả lời

2

Không có API chế độ người dùng cho các chú thích trên tệp đóng mà tôi biết. Vòng lặp bạn đã đề xuất thực sự có thể là cách tốt nhất. Điều duy nhất bạn có thể làm là để xem cho CloseFile trong một trình điều khiển lọc ala Process Monitor, nhưng yuck ...

0

Nếu bạn biết điều gì đó về cách tạo tệp, có thể đợi cho đến khi tệp ngừng phát triển cho X giây, hoặc chờ cho đến khi một tập tin sentinel bị xóa. Hoặc cảm nhận trạng thái của chương trình tạo ra chúng.

+0

Thật không may là tôi không có manh mối về cách tệp được tạo ra hoặc quá trình đặt nó vào thư mục đã xem (nó có thể là bất kỳ chương trình nào, hoặc có thể là người dùng kéo và thả tệp, v.v.). – dreamlax

5

Tôi không nghĩ có thông báo cho loại sự kiện bạn đang tìm kiếm, nhưng là cải tiến, tôi khuyên bạn nên trì hoãn tiến bộ. Bằng cách này, bạn sẽ nhận được thời gian phản hồi nhanh cho các công cụ như kéo/thả và sẽ không hoán đổi CPU với vòng lặp chặt chẽ nếu người dùng giữ tệp mở trong một giờ trong Excel.

int delay= 10; 
while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) { 
     Sleep (delay); 
     if (delay<5120) // max delay approx 5.Sec 
      delay*= 2; 
    } 
    else 
     break; // some other error occurred 
} 
2

Vì tiếc là không có API chế độ người dùng nhưng có cách giải quyết tùy thuộc vào trường hợp sử dụng của bạn (tôi viết dưới đây) có thể làm những gì bạn muốn.

gì làm việc cho tôi trong quá khứ đã đăng ký FILE_NOTIFY_CHANGE_LAST_WRITEthay vìFILE_NOTIFY_CHANGE_FILE_NAME khi gọi ReadDirectoryChangesW:

ZeroMemory(&overlapped, sizeof(OVERLAPPED)); 
overlapped.hEvent = hChangeEvent; 

// ...  
ReadDirectoryChangesW(hSpoolPath, 
         eventBuffer, 
         EVENT_BUF_LENGTH, 
         FALSE, 
         FILE_NOTIFY_CHANGE_LAST_WRITE, // <---- 
         NULL, 
         &overlapped, 
         NULL); 
// ... 
HANDLE events[2]; 

events[0] = hChangeEvent; 
events[1] = hCancelEvent; 

DWORD wRc = WaitForMultipleObjects(2, events, FALSE, DIRECTORY_WATCH_TIMEOUT); 

cuối cùng thời gian ghi được cập nhật ngay sau khi quá trình sở hữu đóng xử lý sau khi tạo file và viết cho nó. Trường hợp sử dụng của tôi là một quá trình nhận yêu cầu HTTP qua TCP/IP và đã viết HTTP-body vào một thư mục, trong đó một quy trình khác đã chọn nó ngay sau khi quá trình nhận được hoàn tất bằng văn bản (và do đó đóng xử lý). Máy chủ http là quá trình duy nhất đã ghi vào thư mục đó, vì vậy tôi có thể dựa vào mô hình tạo-ghi-đóng.

+0

ReadDirectoryChangesW thông báo cho tôi hai lần khi tôi đăng ký FILE_NOTIFY_CHANGE_LAST_WRITE và sau đó thêm tệp vào thư mục. Bạn đã sử dụng thông báo nào? – Will

Các vấn đề liên quan