从多个客户端线程重复执行此代码块一段时间后,我收到一条消息“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:忘记编辑

有帮助吗?

解决方案

我只能建议你使用更“现代”的东西。处理文件的设施。我不知道使用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之间再试一次。

这里有 IS 线程安全问题,虽然我看不出它是如何导致问题的。

问题是重置使用全局FileMode变量。

至于客户端线程 - 你确定他们没有因断开的连接泄漏吗?

在重置和关闭时放置一些调试输出可能很有用,这样您就可以看到每个线程打开文件的时间长度。

你真的需要线程吗?听起来他们正在给你带来麻烦。没有它们,您的代码将更容易调试。

此代码应该可以正常工作。没有与使用线程代码中的文件相关的已知问题(据我所知)。我们经常使用这些习语,一切正常。

我建议添加一些日志代码(在Assign和CloseFile之前)以查看是否执行了a)close并且b)你真的只有10个线程在运行。也许你的线程终止逻辑是错误的,而CloseFile永远不会执行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top