はい、FileShare.Delete はこの問題を引き起こす傾向があります。バックグラウンドで実行され、ファイルをスキャンするすべてのプログラムで使用され、ファイル インデクサーとウイルス スキャナーが一般的な例です。
FileShare.Delete は、バックグラウンド プロセスがまだファイルを開いて読み取り中であっても、別のプロセスがファイルを削除できるようにします。その他のプロセスは、ファイルが実際に削除されたことを知っているため、ファイルが実際に消えなかったことを認識しません。
問題は、他のプロセスが実際に削除されるファイルに依存し、何か他のことを行うときに始まります。通常、同じ名前の新しいファイルを作成することによってトリガーされます。保存に失敗すると、バックアップなしで完全なデータが失われるため、特にファイルを保存する方法は非常に賢明ではありませんが、この間違いは非常に一般的です。
ファイルのディレクトリエントリがまだ存在するため、これは失敗します。ファイルを開いた最後のプロセスがハンドルを閉じるまで、エントリは消えません。ファイルを再度開こうとする他のプロセスは、エラー 5「アクセスが拒否されました」で平手打ちされます。ファイルを削除して再作成しようとしたプロセスを含めます。
回避策は、常に「トランザクション」保存を使用し、上書きする前にファイルの名前を変更することです。.NET では File.Replace() で、ネイティブの winapi では ReplaceFile() で利用できます。手動でも簡単に実行できるワークフローは次のとおりです。
- バックアップファイルを削除し、失敗した場合は停止します
- 古いファイルの名前をバックアップ ファイル名に変更し、失敗した場合は停止します
- 元のファイル名を使用して新しいファイルを書き込み、失敗した場合はバックアップの名前を元に戻します
- バックアップ ファイルを削除し、失敗を無視します
ステップ 2 により、データが失われることはなく、何か問題が発生した場合でも元のファイルはそのまま残ります。手順 4 により、FileShare.Delete が意図したとおりに動作し、他のプロセスがハンドルを閉じると、最終的にバックアップ ファイルが消えることが保証されます。