2009-03-02 143 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變量。

至於客戶端線程 - 你確定他們沒有泄漏到破碎的連接或什麼?