C'è un blog MSDN che descrive perché Windows si comporta come lo descrivi.
Per prima cosa diciamo che quello che vedi è solo su NTFS.
Per testare quello che hai detto, ho scritto un piccolo programma che scrive 40 kB in un file ogni 5 secondi. Il file viene mantenuto aperto tra ogni scrittura. Un secondo programma utilizza FindFirstFileEx
per ottenere la dimensione del file corrente. Come terzo utilizzo dir
in cmd.exe. Con questa configurazione posso vedere esattamente cosa descrivi.
La causa di questo problema è una decisione di progettazione presa in NTFS. In NTFS (come nel filesystem Unix) lo stesso file può trovarsi in due directory - questo si chiama hardlink. Questo significa che hai due directory, ognuna con una voce per il file e hai il file stesso con le sue proprietà. La dimensione del file è una proprietà che appartiene al file, quindi è memorizzata lì. Ma se qualcuno desidera un elenco dei file in una directory con proprietà come la dimensione del file, si otterrebbero prestazioni molto basse se non si dovesse solo leggere la directory stessa, ma anche leggere le informazioni da ogni file. È probabile che i dati per una directory vengano archiviati in sequenza, ma è probabile che i dati per file diversi siano sparsi su tutto il disco. Pertanto NTFS memorizza una copia della dimensione del file nella voce / voci della directory.
Potresti averlo indovinato, anche questo ha un impatto sulle prestazioni. Pensa a 10 hardlink sullo stesso file. Vuoi che NTFS aggiorni 10 voci di directory ogni volta che scrivi su un file? No. Quindi, a partire da Vista, è stata presa una seconda decisione di progettazione: i dati nella voce della directory vengono aggiornati solo alla chiusura del file.
Puoi facilmente verificare che: esegui un programma che scriva su un file e mantenga il file aperto. Esegui dir
e non vedrai una dimensione aggiornata. Oppure scrivi un file con Blocco note (che chiude il file alla fine) e immediatamente la nuova dimensione del file viene visualizzata in dir
Esplora risorse.
Come mai ciò F5aiuta ad aggiornare le dimensioni del file? Explorer chiama GetNamedSecurityInfo che apre internamente il file e lo chiude (è possibile verificarlo in SysInternals Process Monitor ). Se chiamo il GetNamedSecurityInfo
mio programma e poi chiamo FindFirstFileEx
vedo immediatamente la nuova dimensione del file. Quindi il comportamento osservato è esattamente come previsto dalla teoria.
Ma perché non vedi immediatamente la nuova dimensione del file in Explorer? Sembra che Explorer stia prima chiamando FindFirstFileEx
e poi GetNamedSecurityInfo
. Quindi Explorer sta ottenendo le dimensioni precedenti e quindi avvia l'aggiornamento della voce della directory. Se si esegue dir
in cmd.exe, è possibile notare che la voce della directory ha ora la nuova dimensione del file. È solo che Explorer non lo sa ancora. Explorer richiede un secondo F5per ottenere le dimensioni più recenti e quindi attivare nuovamente un aggiornamento.
Dal punto di vista degli sviluppatori di applicazioni, non lo considero un bug di Explorer: questo è un caso speciale per uno dei file system supportati e un'applicazione dovrebbe essere astratta dai file system. Ma poiché Explorer fa parte di Windows, tendo a pensare che Microsoft avrebbe potuto fare di meglio e modificare l'ordine delle chiamate di funzione per ottenere un'esperienza utente migliore.
A proposito, grazie per questa domanda molto interessante! Mi piace aver imparato questo NTFS interno.