Yes, FileShare.Delete tends to cause this problem. Used by any program that runs in the background and scans files, file indexers and virus scanners are the common examples.
FileShare.Delete allows another process to delete the file, even though the background process still has the file opened and is reading from it. That other process will be oblivious that the file didn't actually disappear, for all it knows the file actually got deleted.
The trouble starts when that other process relies on the file actually being removed and does something else. Commonly triggered by creating a new file with the same name. Notably a very unwise way to save a file since it will cause complete data loss without a backup when the save fails, but this mistake is very common.
This will fail because the directory entry for the file is still present, it won't disappear until the last process that has the file opened closes the handle. Any other process that tries to open the file again will be slapped with error 5, "access denied". Including that process that deleted the file and tries to re-create it.
The workaround is to always use "transactional" saves, renaming the file before trying to overwrite it. Available in .NET with File.Replace(), in the native winapi with ReplaceFile(). Also easily done by hand, the workflow is:
- delete the backup file, stop if failed
- rename the old file to the backup filename, stop if failed
- write the new file using the original filename, rename backup back if failed
- delete the backup file, ignore failure
Step 2 ensures that there will never be any data loss, the original file stays intact if anything goes wrong. Step 4 ensures that FileShare.Delete will work as intended, that backup file will disappear eventually when other processes close their handles.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…