2009-03-02 10 views
0

Ich erhalte eine EInOutError mit der Meldung ‚Zu viele offene Dateien‘, wenn sie von einer Reihe von Client-Threads diesen Codeblock wiederholt für einige Zeit ausführen:Zu viele offene Dateien

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

Die Anzahl der Client-Threads ist ungefähr 10 , so dass nur 10 Dateien zu jeder Zeit geöffnet sein können. Gibt es eine Möglichkeit, dass Delphi es ablehnt, Dateien sofort zu schließen? Kann ich sicherstellen, dass es funktioniert? Oder mache ich hier einen Fehler? Dies ist der einzige Ort, wo ich Dateien öffne und der try..finally Block sollte garantieren, dass geöffnete Dateien geschlossen werden, oder?

reedit: vergessen Sie den bearbeiten

+0

Sie meinen AssignFile(), oder? – mghie

+0

Vielleicht AssignFile> Reset ist nicht threadsafe? >.> Versuchen Sie Streams zu verwenden, wie mghie empfiehlt. – PetriW

Antwort

4

Ich kann Ihnen nur empfehlen, die "moderneren" Einrichtungen für den Umgang mit Dateien zu verwenden. Ich weiß nicht, ob es eine Grenze von geöffneten Dateien ist der Windows-API, aber ich nur getestet und konnte leicht öffnen 1000 Ströme parallel:

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; 

Ich habe nie verstanden, warum Menschen immer noch nicht typisierte Dateien anstelle von TStream und seine Nachkommen in neuem Code.

Edit: In Ihrem Kommentar schreiben Sie, dass Sie nur einfache Textdateien lesen wollen - wenn ja gerade ein TStringList erstellen und verwenden seine Loadfromfile() Methode.

+0

Die Textdateien sind im Nur-Text-Format und ich kann das Format nicht ändern. Kann ich mit TReader normale Textdateien anstelle von getaggten Dateien lesen? – jpfollenius

+0

Erstellen Sie einfach eine TStrings-Instanz und verwenden Sie deren LoadFromFile() -Methode - keine Verwendung, um mit Dateien umzugehen, wenn Sie nur eine Textdatei Zeile für Zeile laden müssen. – mghie

+0

Ich habe es so geändert, wie du es vorgeschlagen hast. Es scheint zu funktionieren. Ich verstehe nicht, warum es überhaupt nicht funktioniert hat. Aber ich bin jetzt glücklich ... Danke! – jpfollenius

1

Delphi immidiately in der Closefile schließt. Ihr Beispielcode scheint korrekt zu sein.

Versuchen Sie erneut ohne etwas zwischen Versuch und schließlich.

+0

gleicher Fehler ohne etwas zwischen Versuch und schließlich – jpfollenius

0

Möglicherweise nützlich, um einige Debug-Ausgabe neben dem Zurücksetzen und dem Schließen, so dass Sie sehen können, wie lange jeder Thread die Datei geöffnet hat.

0

Brauchen Sie wirklich Fäden? Es hört sich so an, als würden sie dir Probleme bereiten. Ihr Code wäre einfacher ohne sie zu debuggen.

+0

Die Threads sind einfach für die Simulation mehrerer Clients ... sie fügen keine Komplexität hinzu. – jpfollenius

+0

Ich sehe nichts in dieser oder irgendeiner anderen Frage von Smasher, die darauf hindeutet, Probleme mit Threads zu haben. –

1

Sie laufen nicht auf einem älteren Windows 9x-Computer, oder? Wenn dies der Fall ist, könnte ein DOS-Dateihandle-Problem auftreten.

+0

Nein, ich verwende Windows XP für den Servercomputer und Windows Vista auf dem Clientcomputer – jpfollenius

0

Dieser Code sollte gut funktionieren. Es gibt keine bekannten Probleme im Zusammenhang mit der Verwendung von Dateien aus Thread-Code (soweit ich weiß). Wir verwenden solche Idiome ziemlich regelmäßig und alles funktioniert gut.

Ich würde vorschlagen, einige Logging-Code (vor Assign und CloseFile) hinzufügen, um zu sehen, ob a) schließen ausgeführt wird und b) Sie wirklich nur 10 Threads ausgeführt haben. Möglicherweise ist die Threadbeendigungslogik fehlerhaft und CloseFile wird nie ausgeführt.

+0

Ich denke, dass die globale Variable OpenMode dazu führen kann, dass dateibezogener Code nicht Thread-sicher ist, aber das ist heutzutage behoben, und war sowieso kein großes Risiko, da kaum jemand es schreibt. –

1

Dort IST ein Thread Sicherheitsproblem hier, obwohl ich nicht sehen kann, wie es das Problem verursachen könnte.

Das Problem ist Reset verwendet die globale FileMode-Variable.

Wie für Client-Threads - sind Sie sicher, dass sie nicht bei kaputten Verbindungen oder etwas lecken?

Verwandte Themen