4

ファイルが書き込まれるとすぐにディレクトリからファイルをロードする必要があるプログラムがあります。FileSystemWatcherに、ディレクトリの変更を通知してもらいました。イベントで何が変更されたかを確認するのではなく、ファイルを一覧表示して、見つかったすべての処理を開始します。

まだ書かれているファイルを読み込もうとしないように、次のようなコードがあります。

try {
    fs = fi.Open(FileMode.Open, FileAccess.ReadWrite,
                    FileShare.None);
    message = new byte[fs.Length];
    int br = fs.Read(message, 0, (int)fi.Length);
}
catch (Exception e) {
    // I'll get it next time around
    return;
}
finally {
    if (fs != null)
        fs.Close();
}

問題は、200分の1程度の一部のファイルでは、プログラムがすべてゼロを読み取ることです。ファイルの長さは正しいですが、内容はすべてゼロバイトのようです。後でファイルをチェックすると、実際に正しいデータが含まれていることがわかります。ファイルを開く方法によって、ファイルへの早期アクセスを防ぐことができると思いました。

DOSコマンド'copyInFile_0 * dropdir'(実行ごとに約100ファイル)を使用してファイルをディレクトリにコピーすることでこれをテストしています。おそらく、このコマンドは2つのステップでコピーを実行します:1)スペースの割り当てと2)スペースの塗りつぶしプログラムは時々2つの途中でジャンプします。

これを信頼できるようにコーディングする方法について何かアイデアはありますか?

更新: 私はライティングプログラムを制御できません-それは何でもかまいません。防御的にコーディングする必要があるようです。

4

2 に答える 2

2

競合状態になっています。確実に修正しない限り、ここから(ネットワーク化されたファイルシステムなどで)悪化するだけです。

ファイルを書き込むプログラムに「whatever.tmp」という名前を使用して各ファイルを書き込んでもらい、それを閉じてから名前を変更してみてください。読み取るときは、.tmpファイルを無視してください。

または、「sentinel」などの名前の長さゼロのファイルをディレクトリに保持します。別のファイルの書き込みが成功するたびに、ファイルを書き込むプログラムにセンチネルファイルを再書き込みさせます。次に、変更日時がセンチネルファイルの変更日時>=であるファイルを読み取ろうとしないでください。

または、ファイルの作成者を制御できない場合は、各ファイルの変更日時を現在のシステム日時と照合します。ファイルを読み取ろうとする前に、ファイルを適切な量(小さい場合は数秒、大きい場合は長く)エージングします。

幸運を。これは首の悪名高い痛みです。

于 2011-01-20T00:23:07.090 に答える
1

ええと、@OllieJonesによる以前の投稿には同意しません。

ファイルへの排他的アクセスはすでに確立されているため、競合状態の問題はありません。

作家の振る舞いをもっとよく調べてみるべきだと思います。そして、読み取り専用でファイルアクセスへの干渉を減らし、すべてのアクセスを共有してみてください。

fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

これにより、読み取りが失敗する可能性がありますが、書き込みエラーは減少します。安全に読み取るタイミングを決定するために、ファイル時間やファイルサイズなどを確認できます。その後に多くのファイルが書き込まれる場合は、2番目のファイルが作成された後に最初のファイルの読み取りを開始できます。

于 2011-01-20T16:42:20.133 に答える