[解決済み】IOException: ファイル 'ファイルパス' は他のプロセスによって使用されているため、プロセスはアクセスできません。
質問
あるコードがあり、それが実行されると
IOException
と言っています。
このプロセスはファイル 'filename' を使用中のため、アクセスできません。 別のプロセス
これはどういうことですか、またどうすればいいですか?
解決方法は?
原因は何ですか?
エラーメッセージは非常に明確です。ファイルにアクセスしようとしているのに、他のプロセス(または同じプロセス)がそのファイルで何かを行っている(そして、共有を許可していない)ために、アクセスできないのです。
デバッギング
特定のシナリオによっては、かなり簡単に解決できる(あるいはかなり理解しにくい)かもしれません。いくつか見てみましょう。
そのファイルにアクセスできるのはあなたのプロセスだけです。
を確認しましたか?
その他
プロセスは、あなた自身のプロセスです。もし、そのファイルをプログラムの別の部分で開いていることが分かっているのなら、まず、使用後にファイルハンドルをきちんと閉じているかどうかをチェックする必要があります。このバグがあるコードの例を示します。
var stream = new FileStream(path, FileAccess.Read);
var reader = new StreamReader(stream);
// Read data from this file, when I'm done I don't need it any more
File.Delete(path); // IOException: file is in use
幸いなことに
FileStream
が実装されています。
IDisposable
の中ですべてのコードをラップするのは簡単です。
using
ステートメントを使用します。
using (var stream = File.Open("myfile.txt", FileMode.Open)) {
// Use stream
}
// Here stream is not accessible and it has been closed (also if
// an exception is thrown and stack unrolled
このパターンは、例外が発生した場合にファイルが開かれたままにならないようにすることもできます(ファイルが使われている理由は、何か問題が発生し、誰もそれを閉じなかったということかもしれません。 この記事 の例)。
もし、すべてがうまくいっていて(例外が発生した場合でも、開いたファイルは必ず閉じている)、複数のスレッドが動作している場合、2つの選択肢があります:ファイルアクセスをシリアライズするためにコードを作り直すか(常に可能で、常に望んでいるわけではありません)。 リトライパターン . これはI/O操作ではかなり一般的なパターンです。何かをしようとして、エラーの場合は待って再試行します(例えば、Windowsシェルがファイルが使用中で、削除できないことを通知するのに時間がかかる理由を自問したことがありますか)。C#でこれを実装するのはとても簡単です。 ディスクI/O , ネットワーキング そして データベースアクセス ).
private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;
for (int i=1; i <= NumberOfRetries; ++i) {
try {
// Do stuff with file
break; // When done we can break loop
}
catch (IOException e) when (i <= NumberOfRetries) {
// You may check error code to filter some exceptions, not every error
// can be recovered.
Thread.Sleep(DelayOnRetry);
}
}
StackOverflowで非常によく見かける一般的なエラーにご注意ください。
var stream = File.Open(path, FileOpen.Read);
var content = File.ReadAllText(path);
この場合
ReadAllText()
はファイルが使用中であるため失敗します (
File.Open()
の前の行にある)。あらかじめファイルを開いておくことは、不要であるばかりでなく、間違いでもあるのです。同じことが、すべての
File
を返さない関数は
ハンドル
を作業中のファイルに追加します。
File.ReadAllText()
,
File.WriteAllText()
,
File.ReadAllLines()
,
File.WriteAllLines()
などがあります(例えば
File.AppendAllXyz()
関数)は、すべて単独でファイルを開いたり閉じたりします。
そのファイルにアクセスできるのはあなたのプロセスだけではありません。
あなたのプロセスがそのファイルにアクセスする唯一のものでない場合、相互作用はより困難になる可能性があります。A
リトライパターン
が役に立ちます(もし、そのファイルが他の誰にも開かれていないはずなのに開かれている場合は、Process Explorerのようなユーティリティーで
誰
を実行している。
何
).
回避する方法
該当する場合は、必ず を使って ステートメントを使用してファイルを開くことができます。前の段落で述べたように、これは多くの一般的なエラーを回避するのに積極的に役立ちます ( この記事 に関する例として 使い方 ).
可能であれば、特定のファイルへのアクセスの所有者を決め、いくつかのよく知られたメソッドを通じてアクセスを集中化するようにしてください。例えば、プログラムが読み書きするデータファイルがある場合、すべてのI/Oコードを1つのクラスで管理する必要があります。そうすれば、デバッグが容易になるし(そこにブレークポイントを置けば、誰が何をしているかがわかるから)、(必要なら)複数のアクセスに対する同期ポイントにもなる。
I/O操作は常に失敗する可能性があることを忘れないでください。よくある例がこれです。
if (File.Exists(path))
File.Delete(path);
もし
誰か
の後にファイルを削除します。
File.Exists()
よりも前に
File.Delete()
を投げることになります。
IOException
を、誤って安全だと感じるかもしれない場所に設置する。
可能な限り
リトライパターン
を使用する場合、また
FileSystemWatcher
は、アクションを延期することを検討してください(通知はされますが、アプリケーションはまだそのファイルのみで作業している可能性があるため)。
高度なシナリオ
いつもそう簡単にはいかないので、誰かとアクセスを共有する必要があるかもしれません。例えば、最初から読んでいて、最後まで書いている場合、少なくとも2つの選択肢があります。
1) 同じものを共有する
FileStream
を、適切な同期関数を使って(なぜなら
スレッドセーフでない
). 参照
これ
と
これ
の投稿を例として挙げます。
2)使用
FileShare
を列挙し、他のプロセス(または自プロセスの他の部分)が同じファイルに同時にアクセスできるようにOSに指示します。
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}
この例では、書き込み用にファイルを開き、読み込み用に共有する方法を示しました。読み込みと書き込みが重なった場合、未定義または無効なデータになってしまうので、注意してください。これは、読み込みの際に処理しなければならない状況です。また、これでは
stream
スレッドセーフなので、何らかの方法でアクセスを同期させない限り、このオブジェクトを複数のスレッドで共有することはできません(以前のリンクを参照してください)。他の共有オプションも利用可能で、より複雑なシナリオを開くことができます。以下を参照してください。
MSDN
をご覧ください。
一般的に N 制御されたシナリオでは、同時書き込みを有効にすることもできますが、これはこの回答内の数行のテキストで一般化することはできません。
次のようなことは可能ですか? アンロック 他のプロセスで使用されているファイルですか?安全とは限りませんし、そう簡単ではありませんが、そうです。 可能です .
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み] 山積みされた靴下を効率よく組み合わせるには?
-
[解決済み] IDisposable インターフェースの正しい使用法
-
[解決済み] C#がforeachで変数を再利用するのは理由があるのか?
-
[解決済み] Try-catchは私のコードをスピードアップさせるか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Static readonly」対「const」。
-
[解決済み】大文字・小文字を区別しない「Contains(string)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] メンバー '<メンバー名>' にインスタンス参照でアクセスできない
-
[解決済み] エンティティタイプ <type> は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】C#はJavaのcharAt()と同等?)
-
[解決済み】"The ConnectionString property has not been initialized "を修正する方法
-
[解決済み】SmtpException: トランスポート接続からデータを読み取れません:net_io_connectionclosed
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】 C# 条件演算子エラー 代入、call、increment、decrement、await、new object 式のみ文として使用可能です。
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015