2009-03-02 140 views
0

我得到的消息“打开的文件太多”的EInOutError从多个客户端线程的重复执行这个代码块一段时间时:打开的文件太多

var InputFile : Text; 
... 
Assign (InputFile, FileName); 
Reset (InputFile) 
try 
    // do some stuff 
finally 
    CloseFile (InputFile); 
end; 

客户端线程的数量大约是10 ,所以任何时候只能打开10个文件。 Delphi有没有可能立即拒绝关闭文件?我能确保它确实吗?或者我在这里犯了一个错误?这是我打开文件的唯一地方,try..finally块应该保证打开的文件关闭,不是吗?

REEDIT:忘记编辑

+0

你的意思是AssignFile(),对吧? – mghie 2009-03-02 09:40:51

+0

也许AssignFile>重置不是线程安全的? >。>按照mghie的建议尝试使用流。 – PetriW 2009-03-02 10:19:39

回答

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()方法

1

Delphi在CloseFile中立即关闭。您的示例代码似乎是正确的。

再次尝试之间没有任何尝试和最后。

+0

同样的错误没有任何尝试和最后 – jpfollenius 2009-03-02 09:16:12

0

将复位和关闭一起放置一些调试输出可能很有用,因此您可以看到每个线程有多长时间打开该文件。

0

你真的需要线程吗?这听起来像他们正在造成你的问题。没有它们,您的代码将更容易进行调试。

+0

线程只是为了模拟多个客户端...他们不增加任何复杂性。 – jpfollenius 2009-03-02 09:25:54

+0

我在这个或任何Smasher的其他问题中都没有看到任何暗示有线程问题的问题。 – 2009-03-02 15:27:03

1

您不是在基于Windows 9x的较早版本的计算机上运行该程序,是吗?如果是这样,你可能会遇到DOS文件句柄问题。

+0

不,我在客户端机器上使用windows xp作为服务器和Windows Vista – jpfollenius 2009-03-02 09:30:31

0

此代码应该工作得很好。没有已知的使用线程代码中的文件的问题(据我所知)。我们经常使用这样的习语,一切正常。

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

1

There IS这里是一个线程安全问题,虽然我看不出它是如何引起问题的。

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

至于客户端线程 - 你确定他们没有泄漏到破碎的连接或什么?