从多个客户端线程重复执行此代码块一段时间后,我收到一条消息“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块应该保证打开的文件关闭,不应该吗?
REEDIT:忘记编辑
答案 0 :(得分:4)
我只能建议您使用更“现代”的设施来处理文件。我不知道使用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()< / em>方法。
答案 1 :(得分:1)
Delphi在CloseFile中立即关闭。您的示例代码似乎是正确的。
在try和finally之间再试一次。
答案 2 :(得分:1)
您没有在较旧的基于Windows 9x的计算机上运行此功能,是吗?如果是这样,您可能会遇到DOS文件句柄问题。
答案 3 :(得分:1)
这里有 IS 线程安全问题,虽然我看不出它是如何导致问题的。
问题是重置使用全局FileMode变量。
至于客户端线程 - 你确定它们没有在断开的连接上泄漏吗?
答案 4 :(得分:0)
在重置和关闭时放置一些调试输出可能很有用,这样您就可以看到每个线程打开文件的时间长度。
答案 5 :(得分:0)
你真的需要线程吗?听起来他们正在给你带来麻烦。没有它们,您的代码将更容易调试。
答案 6 :(得分:0)
此代码应该可以正常工作。没有与使用线程代码中的文件相关的已知问题(据我所知)。我们经常使用这些习语,一切正常。
我建议添加一些日志代码(在Assign和CloseFile之前)以查看是否执行了a)close并且b)你真的只有10个线程在运行。也许你的线程终止逻辑是错误的,而CloseFile永远不会执行。