2009-03-02 9 views
0

je reçois un EInOutError avec le message « Trop de fichiers ouverts » lors de l'exécution de ce bloc de code à plusieurs reprises pendant un certain temps à partir d'un certain nombre de threads client:Trop de fichiers ouverts

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

Le nombre de threads client est d'environ 10 , donc seulement 10 fichiers peuvent être ouverts à tout moment. Est-il possible que Delphi refuse de fermer les dossiers tout de suite? Puis-je m'assurer que c'est le cas? Ou est-ce que je fais une erreur ici? C'est le seul endroit où j'ouvre des fichiers et le bloc try..finally devrait garantir que les fichiers ouverts seront fermés, n'est-ce pas?

remodifier: oublier le modifier

+0

Vous voulez dire AssignFile(), n'est-ce pas? – mghie

+0

Peut-être AssignFile> Reset n'est pas threadsafe? >. Essayez d'utiliser des flux comme le recommande mghie. – PetriW

Répondre

4

Je ne peux que vous conseiller d'utiliser les installations les plus «modernes» pour traiter les fichiers. Je ne sais pas s'il y a une limite de fichiers ouverts à l'aide de l'API Windows, mais je viens de tester et pourrait facilement ouvrir 1000 flux en parallèle:

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; 

Je ne l'ai jamais compris pourquoi les gens utilisent encore des fichiers non typées au lieu de TStream et ses descendants dans le nouveau code.

Edit: Dans votre commentaire, vous écrivez que vous voulez seulement lire les fichiers texte en clair - si oui il suffit de créer un TStringList et utiliser son LoadFromFile() méthode.

+0

Les fichiers texte sont au format texte brut et je ne peux pas changer le format. Puis-je utiliser TReader pour lire des fichiers texte normaux au lieu de fichiers étiquetés/typés? – jpfollenius

+0

Il suffit de créer une instance de TStrings et d'utiliser sa méthode LoadFromFile() - aucune utilisation pour traiter des fichiers si tout ce que vous avez à faire est de charger un fichier texte ligne par ligne. – mghie

+0

Je l'ai changé comme vous l'avez proposé. Cela semble fonctionner. Je ne comprends pas pourquoi cela n'a pas fonctionné en premier lieu. Cependant, je suis content pour le moment ... merci! – jpfollenius

1

Delphi ferme immidiately dans le CloseFile. Votre code d'exemple semble être correct.

Essayez à nouveau sans rien entre essayer et enfin.

+0

même erreur sans rien entre essayer et enfin – jpfollenius

0

Peut-être utile de mettre une sortie de débogage à côté de la réinitialisation et la fermeture de sorte que vous pouvez voir combien de temps chaque thread a ouvert le fichier.

0

Avez-vous vraiment besoin de fils? On dirait qu'ils vous causent des problèmes. Votre code serait plus facile à déboguer sans eux.

+0

Les threads sont simplement pour simuler plusieurs clients ... ils n'ajoutent aucune complexité. – jpfollenius

+0

Je ne vois rien dans cette question ou dans aucune des autres questions de Smasher qui pourrait suggérer des problèmes avec les threads. –

1

Vous ne l'utilisez pas sur un ancien ordinateur Windows 9x, n'est-ce pas? Si c'est le cas, vous risquez de rencontrer un problème de gestionnaire de fichiers DOS.

+0

non, j'utilise Windows XP pour la machine serveur et Windows Vista sur la machine client – jpfollenius

0

Ce code devrait fonctionner correctement. Il n'y a pas de problèmes connus liés à l'utilisation de fichiers à partir du code fileté (pour autant que je sache). Nous utilisons assez régulièrement de tels idiomes et tout fonctionne bien.

Je suggère d'ajouter du code de journalisation (avant Assign et CloseFile) pour voir si a) close est exécuté et b) vous n'avez vraiment que 10 threads en cours d'exécution. Peut-être votre logique de terminaison de thread est-elle défectueuse et CloseFile ne s'exécute jamais.

+0

Pendant un moment, je pense que la variable globale OpenMode pourrait rendre le code lié aux fichiers non-thread-safe, mais cela est corrigé de nos jours, et n'était pas un risque majeur puisque presque personne ne l'écrit. –

1

Il ya IS un problème de sécurité de thread ici, même si je ne vois pas comment cela pourrait causer le problème.

Le problème est Réinitialiser utilise la variable globale FileMode. Comme pour les threads client - êtes-vous sûr qu'ils ne fuient pas sur des connexions cassées ou quelque chose?

Questions connexes