2009-11-17 12 views
5

Sto guardando una directory chiamando lo ReadDirectoryChangesW in modo sincrono. Quando un nuovo file è disponibile, provo ad accedervi immediatamente con CreateFile con GENERIC_READ e FILE_SHARE_READ, ma questo mi dà ERROR_SHARING_VIOLATION. Il processo che inserisce il file nella directory controllata non termina la scrittura quando cerco di leggerlo.Attendere fino a quando un file è disponibile per la lettura con Win32

C'è un modo per attendere in modo affidabile finché il file non è disponibile per la lettura? Posso mettere il metodo in un loop come quello qui sotto, ma spero che ci sia un modo migliore.

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

Presumo che questo sia C++? Se è C#, esiste un oggetto SystemFileWatcher nel BCL che è possibile utilizzare. –

+0

Win32 == C API, mi ripeterò. – dreamlax

risposta

2

Non ci sono API in modalità utente per le notifiche su un file chiuso di cui sono a conoscenza. Il ciclo che hai proposto è probabilmente il modo migliore. L'unica altra cosa che potresti fare sarebbe guardare CloseFile in un driver di filtro ala Process Monitor, ma schifo ...

0

Se sai qualcosa su come viene creato il file, forse aspetta che il file smetta di crescere per X secondi, o attendere fino all'eliminazione di un file sentinella. O percepire lo stato del programma che li crea.

+0

Purtroppo non ho idea di come viene generato il file o del processo che lo sta inserendo nella cartella controllata (potrebbe essere un qualsiasi programma, o potrebbe essere l'utente che trascina e rilascia un file, ecc.). – dreamlax

5

Non penso che ci sia una notifica per il tipo di evento che stai cercando, ma come miglioramento, suggerirei ritardi progressivi. In questo modo otterrete tempi di risposta rapidi per cose come un trascinamento/rilascio e non affogheranno la CPU con un ciclo stretto se l'utente mantiene il file aperto per un'ora in 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

Come ha detto @ Matt Davis, non c'è purtroppo alcuna API user-mode, ma c'è una soluzione che a seconda del caso d'uso (I miei ho scritto qui di seguito) può fare proprio quello che vuoi.

cosa ha funzionato per me in passato è stata la registrazione per FILE_NOTIFY_CHANGE_LAST_WRITEinvece diFILE_NOTIFY_CHANGE_FILE_NAME al momento della chiamata 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); 

L'ultima volta scrittura viene aggiornato non appena il processo proprietario chiude l'handle dopo la creazione del file e scrivendoci.

Il mio caso d'uso era un processo che riceveva richieste HTTP via TCP/IP e scriveva il corpo HTTP in una directory, dove un altro processo lo prelevava non appena il processo di ricezione era finito a scrivere (e di conseguenza chiudendo il occupatene. L'http-server era l'unico processo che scriveva su quella directory, quindi potevo fare affidamento sul modello create-write-close.

+0

ReadDirectoryChangesW mi notifica due volte quando mi registro per FILE_NOTIFY_CHANGE_LAST_WRITE e quindi aggiungo un file alla cartella. Quale notifica hai usato? – Will

Problemi correlati