質問
いくつかのクライアントスレッドからしばらくの間このコードブロックを繰り返し実行すると、メッセージ「Too many open files」でEInOutErrorが表示されます。
var InputFile : Text;
...
Assign (InputFile, FileName);
Reset (InputFile)
try
// do some stuff
finally
CloseFile (InputFile);
end;
クライアントスレッドの数は約10であるため、一度に開くことができるファイルは10個だけです。 Delphiがすぐにファイルを閉じることを拒否する可能性はありますか?確実に実行できますか?それとも私はここで間違いを犯していますか?これは私がファイルを開く唯一の場所であり、try..finallyブロックは開かれたファイルが閉じられることを保証するはずです、そうではありませんか?
再編集:編集を忘れる
解決
より多くの「モダン」を使用することをお勧めします。ファイルを処理するための機能。 Windows APIを使用して開くことができるファイルに制限があるかどうかはわかりませんが、テストしただけで、1000個のストリームを並行して簡単に開くことができます。
procedure TForm1.Button1Click(Sender: TObject);
var
Strs: TList;
i: integer;
begin
Strs := TList.Create;
try
for i := 1 to 1000 do begin
Strs.Add(TFileStream.Create('D:\foo.txt', fmOpenRead or fmShareDenyWrite));
end;
finally
FreeObjectList(Strs);
end;
end;
なぜ人々が新しいコードで TStream とその子孫の代わりに型付けされていないファイルを使用するのか理解できません。
編集:コメントには、プレーンテキストファイルのみを読みたいと書いています。その場合は、 TStringList を作成して、その LoadFromFile()メソッド。
他のヒント
これは古いWindows 9xベースのコンピューターでは実行していませんか?その場合、DOSファイルハンドルの問題が発生している可能性があります。
DelphiはCloseFileですぐに閉じます。サンプルコードは正しいようです。
tryとfinallyの間に何もせずに再試行してください。
問題が発生する原因はわかりませんが、ここにはスレッドセーフの問題があります 。
問題は、リセットがグローバルFileMode変数を使用することです。
クライアントスレッドについては、接続の切断などでリークが発生していないことを確認しますか?
各スレッドがファイルを開いている時間を確認できるように、ResetおよびCloseとともにデバッグ出力を配置すると便利な場合があります。
本当にスレッドが必要ですか?問題が発生しているようです。あなたのコードはそれらなしでデバッグする方が簡単でしょう。
このコードは問題なく動作するはずです。スレッドコードからのファイルの使用に関連する既知の問題はありません(私の知る限り)。このようなイディオムをかなり定期的に使用しており、すべてが正常に機能します。
(AssignおよびCloseFileの前に)ロギングコードを追加して、a)closeが実行され、b)実際に実行しているスレッドが10個だけかどうかを確認することをお勧めします。スレッド終了ロジックに障害があり、CloseFileが実行されない可能性があります。