質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

16352閲覧

File.Delete メソッドが遅延する。

nobysanz

総合スコア42

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2019/05/15 22:51

質問です。
以下のような処理を行っておりますが、File.Delete メソッド実行後、File.Move実行時に、
IOException 「既に存在するファイルを作成することはできません。」が発生します。(必ずではありません)

File.Delete 処理は遅延処理なのでしょうか?
ご教授をお願いします。

環境:Windows10 pro (64bit)
言語:C# / .NET Framework4.0

C#

1 Boolean rtn = true; 2 try 3 { 4 //移動先ファイルを存在チェック 5 if (File.Exists("c:\work_dst\test.txt")) 6 { 7   //存在すれば削除する。 8 File.Delete("c:\work_dst\test.txt"); 9 } 10 //ファイル移動する。 11 File.Move("c:\work_src\test.txt", "c:\work_dst\test.txt"); 12 } 13 catch (System.IO.PathTooLongException e) 14 { 15 rtn = false; 16 throw new PathTooLongException("例外[PathTooLongException] Msg=" + e.Message); 17 } 18 catch (System.ArgumentNullException e) 19 { 20 rtn = false; 21 throw new ArgumentNullException("例外[ArgumentNullException] Msg=" + e.Message); 22 } 23 catch (System.ArgumentException e) 24 { 25 rtn = false; 26 throw new ArgumentException("例外[ArgumentException] Msg=" + e.Message); 27 } 28 catch (System.IO.DirectoryNotFoundException e) 29 { 30 rtn = false; 31 throw new DirectoryNotFoundException("例外[DirectoryNotFoundException] Msg=" + e.Message); 32 } 33 catch (System.NotSupportedException e) 34 { 35 rtn = false; 36 throw new NotSupportedException("例外[NotSupportedException] Msg=" + e.Message); 37 } 38 catch (System.UnauthorizedAccessException e) 39 { 40 rtn = false; 41 throw new UnauthorizedAccessException("例外[UnauthorizedAccessException] Msg=" + e.Message); 42 } 43 catch (System.IO.FileNotFoundException e) 44 { 45 rtn = false; 46 throw new FileNotFoundException("例外[FileNotFoundException] Msg=" + e.Message); 47 } 48 catch (System.IO.IOException e) 49 { 50 rtn = false; 51 throw new IOException("例外[IOException] Msg=" + e.Message); 52 } 53 return rtn; 54

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

OS の処理が終わっていない可能性はありますね。削除した後、File.Exists が false を返すまで待ってみてはどうでしょう?

投稿2019/05/15 23:06

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobysanz

2019/05/15 23:08

コメントありがとうございます。もしかして、File.Delete メソッドは非同期処理ということでしょうか?
Zuishin

2019/05/15 23:13

削除自体は同期処理ですが、その後は OS の実装に依存します。
Zuishin

2019/05/16 00:22

たとえば、ファイルの削除 API が呼ばれたとき、OS はまず他のプロセスが当該ファイルをオープンできないようロックします。次にそのファイルを削除し、その後ロックを外します。 このファイルを削除し、ロックを外す前に処理が戻ってきた場合、次の処理でファイルを移動しようとした際にロックが外れていないので削除できないということは十分考えられます。
guest

0

System.IO.File.Deleteの中を見た感じでは、中でWin32APIのDeleteFileが呼ばれています。
このAPIのリファレンスには

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

と、最後のハンドルがCloseされた時に削除が実行されるとあります。
これを信じれば、ファイルオープン→DeleteFile(ここでは削除されない)→ファイルクローズ(ここで削除)
となるため、誰かが対象のファイルを先にオープンしていることがあると、即座には削除されないケースが考えられます。
※セキュリティソフトが掴んでいる場合もありそうです(txtは掴まないかな・・・)。

対策としてはZuishinさんがコメントされている方法で良いと思います。

こちらの記事も参考になりそうです。
消えないファイルの話(Delete Pending)

投稿2019/05/16 05:15

takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

質問に対する回答は、既に出ているものが正しいと思います。

ところで、何故「存在確認してあったら削除して移動」なんていう、人の手でやるような操作にこだわっているのかがわからないです。Deleteができるということは、ファイルに対する完全な操作権限を持っている前提だと思うので、単純に「上書きして塗り潰してから元を消す」ではダメなのでしょうか?元を消す必要すらない気もしますが。

csharp

1File.Copy(@"c:\work_src\test.txt", @"c:\work_dst\test.txt", overwrite: true); 2File.Delete(@"c:\work_src\test.txt");

投稿2019/05/17 07:36

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobysanz

2019/05/17 07:57

コメントありがとうございます。 今回の事象について回避する方法は、皆さんからのコメントで問題なく解決できることは 理解しております。助かってます。 ただ、File.Delete メソッドを使う場合は、注意が必要ということですよね。 このような、タイミングによって事象が出てしまうパターンは、突然事象が発生し その後、再現しなかったとか、パソコン(処理スペックが向上したとか) を更新したら、発生するようになったとか、不可解事象の要因なるので、メカニズムを はっきりさせたいと思っていました。
Zuishin

2019/05/17 12:00 編集

メカニズムなんて OS のアップデートやアンチウィルスソフトやオンラインストレージサービスやディスクドライバーなんかで簡単に変わるのでそこをあてにしても仕方ありません。
pepperleaf

2019/05/17 11:56

いや、昔から、削除直後に作成でエラーってのはよくある事。(Windowsに限らず) まず、ファイルは外部機器にあります。そこに削除を依頼する。当然、CPUより、遅い。すぐに作成依頼したら、まず、ダメでしょって。 最近の方がマシって気がします。(レスポンスが速いので)
nobysanz

2019/05/20 05:24

コメントありがとうございます。 そうですね、ファイルは外部リソースのものですよね。勉強になりました。
guest

0

お手軽に
File.Delete("c:\work_dst\test.txt");
Application.DoEvents();
}

でどうですか。

投稿2019/05/16 06:13

mhc00160

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/05/16 06:19

Application.DoEvents(); は Windows フォームの時にしか使えませんが、この質問は Windows フォームに限定されていません。 またこれはメッセージを処理するメソッドで、実用上は問題ないかもしれませんが、ファイル操作とは特に関係ないので、一回呼び出すだけでは理論上は適切にウエイトを入れたとは言えません。
nobysanz

2019/05/17 07:04

コメントありがとうございます。 いずれにしても、File.Delete 実行後に、File.Move する場合に、ファイルが存在するタイミングが発生するとのことですよね。 これは、File.Delete 仕様なのでしょうか、削除完了を保証してくれても良いかと思います。 CPUの処理速度(性能)で発生頻度がかわるようなことがあるのでしょうか? 当該事象が発生するメカニズムは以下のような流れ感じでしょうか? ①File.Delete 実行 → ②削除API 実行   → ③OS側の操作(時間がかかる?、待たされる?)      まだ、ファイル削除されていない状態で      ②の実行後にプログラムが戻る。 ③File.Move実行    ファイルが存在するため、エラー発生する。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問