While Not EOF(F) dans Thread [Résolu]

cs_Jean_Jean 639 Messages postés dimanche 13 août 2006Date d'inscription 5 mai 2016 Dernière intervention - 29 avril 2012 à 10:36 - Dernière réponse : cs_Jean_Jean 639 Messages postés dimanche 13 août 2006Date d'inscription 5 mai 2016 Dernière intervention
- 1 mai 2012 à 17:27
Bonjour

J'ai un souci avec la détection d'une Fin de lecture de fichier dans un Thread:

1. Code qui marche :
Je détecte la Fin du parcours de Fichier avec le compteur Interne

procedure TMyThread4.Execute;
var
  F        : TextFile;
  L        : String;
  FinTrait : Boolean;
begin
  {initialisations locales}
  ...
  FinTrait   := False;  
  FMessage   := 'Traitement Long en cours...';
  Synchronize(AfficherMessage);
  
  {DEBUT TRAITEMENT LONG}
  {1. Transfert du Fichier dans une TList...}
   ...
   Try
    AssignFile(F,FicTest);
    Reset(F);
    While Not FinTrait and Not Terminated do
    begin
      Read(F,L);
      Inc(FCount);
      ListLignesFic.Add(L);
      ...
      Synchronize(AfficherProgression);
      if FCount > FMaxCount then FinTrait := True;
    end;
    ...
    FMsgLog := '  - Fichier Trié';
    Synchronize(AffichageMemoLog);
  Finally
    CloseFile(F);
  End;
end;


2. Code qui ne marche pas
Détection classique de Fin de fichier par EOF(F) en remplacement du Booléen précédent Fin Trait
procedure TMyThread4.Execute;
var
  F        : TextFile;
  L        : String;
begin
  {initialisations locales}
  ...
  FMessage   := 'Traitement Long en cours...';
  Synchronize(AfficherMessage);
  
  {DEBUT TRAITEMENT LONG}
  {1. Transfert du Fichier dans une TList...}
   ...
   Try
    AssignFile(F,FicTest);
    Reset(F);
    While Not EOF(F) and Not Terminated do
    begin
      Read(F,L);
      Inc(FCount);
      ListLignesFic.Add(L);
      ...
      Synchronize(AfficherProgression);
    end;
    ...
    FMsgLog := '  - Fichier Trié';
    Synchronize(AffichageMemoLog);
  Finally
    CloseFile(F);
  End;
end;


Le Thread continue sa progression sur Inc(FCount) et ne s'arrête jamais.
J'ai donc l'impression que le EOF n'est pas pris en compte par le Thread Créé.

Question:
1. Dans ce cas, comment se prémunir d'une éventuelle erreur de lecture au delà de la fin de fichier.
Ce qui est bizarre, c'est que mon compteur continue bien au-delà de la valeur du fichier mais ne produit pas d'erreur
2. Ma préférence serait de mettre ma boucle de lecture de Fichier dans la Fiche et d'envoyer au thread, les variables dont il a besoin pour l'affichage. mais je ne sais pas si c'est valable ...

Je progresse mais pas facile à maitriser ces threads... Merci pour vos éclairages.




Jean_Jean
Afficher la suite 

9 réponses

Répondre au sujet
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 30 avril 2012 à 15:22
+3
Utile
Salut,

j'ai testé et en changeant:
  L        : string;


en
  L        : char;


ça fonctionne très bien .. enfin chez moi testé sous D7 & D2009
mais à ta place j'utiliserai les Streams et non AssignFile !!


[hr]@+Cirec
[hr]
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Cirec
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 30 avril 2012 à 15:49
+3
Utile
ps:

mets aussi AssignFile avant try :
   AssignFile(F,FicTest);
   try
     ...


si l'assignation échoue il n'est pas utile fermer F (Close(F)) puisque non assigné.

[hr]@+Cirec
[hr]
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Cirec
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 1 mai 2012 à 10:01
+3
Utile
... mais le teste je l'ai fait avec ton code hein (pas avec les Streams)!!
as-tu déjà essayé, dans ton code, de remplacer "string" par "Char" ?



[hr]@+Cirec
[hr]
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Cirec
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 1 mai 2012 à 12:55
+3
Utile
Salut,
l'utilisation de Read et de string dans un fichier texte même en utilisant SetLineBreakStyle est.......en gros tu rentres dans un fichier qui ne te donnera jamais de marqueur de fin,donc tu rentres dans une boucle infinie ! Readln te permet d'avoir des marqueurs de fin correcte et de ne pas rentrer dans cette boucle...remplacer string par char permet de faire ce que tu veux,mais caractère par caractère et donc d'arriver à la fin du fichier,mais en terme de performance c'est vraiment pas top...
Pour te convaincre voici une boucle infinie avec Read et un fichier texte de 2 lignes :


procedure TForm1.Button1Click(Sender: TObject);
var
F : TextFile;
S : string;
begin
AssignFile(F,ExtractFilePath(Application.ExeName)+'Test.txt');
Reset(F);
while not eof(F) do
begin
Read(F,S);
ListBox1.Items.Add(S);
end;
CloseFile(F);
ShowMessage('Fin fichier');
end;
 

Moi je ferais comme cirec en utilisant les streams...
Bon courage @+yanb
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_yanb
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 30 avril 2012 à 12:00
0
Utile
Salut,
Et en utilisant readln à la place de read...
@+Yanb
Commenter la réponse de cs_yanb
cs_Jean_Jean 639 Messages postés dimanche 13 août 2006Date d'inscription 5 mai 2016 Dernière intervention - 30 avril 2012 à 14:17
0
Utile
Salut yanb,

Merci de m'avoir répondu.
Non Readln ne change rien, d'ailleurs avec un Fichier texte, il vaut mieux utiliser readln...
Je pense que le problème vient du fait que les procédures et méthodes de la VCL sont en réalité incluses dans le Thread principal de l'application...
D'où mon intérêt supplémentaire pour essayer de mettre la boucle princiale dans une procédure de la Fiche... Mais c'est une autre structure que celle que je met ici dans ce post...
En attendant, je peux gérer le parcours de mon fichier dans le exécute du Thread par un boolean.
... Je vous tiens au courant... J'attends de résoudre ce problème pour publier mon code...
Beaucoup d'exemples fictifs de thread sur les sites mais peu de réels applis même simplifiées...

@+


Jean_Jean
Commenter la réponse de cs_Jean_Jean
cs_Jean_Jean 639 Messages postés dimanche 13 août 2006Date d'inscription 5 mai 2016 Dernière intervention - 30 avril 2012 à 22:43
0
Utile
Salut,

Merci Cirec, Oui le AssignFile avant le try, ok!
je vais essayer avec les stream...

@+

Jean_Jean
Commenter la réponse de cs_Jean_Jean
Cirec 4217 Messages postés vendredi 23 juillet 2004Date d'inscription 3 avril 2018 Dernière intervention - 1 mai 2012 à 15:35
0
Utile
@yanb:

oui on le sait que c'est très long ... mais le but de cette "procédure" c'est justement d'avoir une procédure longue afin de faire une démo concrète de l'utilisation d'un Thread (cf. son code):
" FMessage := 'Traitement Long en cours...';"


[hr]@+Cirec
[hr]
Commenter la réponse de Cirec
cs_Jean_Jean 639 Messages postés dimanche 13 août 2006Date d'inscription 5 mai 2016 Dernière intervention - 1 mai 2012 à 17:27
0
Utile
re bonjour,

Merci pour vos commentaires. Je réponds dans l'ordre.

1. Effectivement, ça marche avec un type Char. Mais pour la démo, j'utilisai un TextFile car ça me paraissait plus rapide de ligne par ligne... Comme quoi!

2. Dans un Fichier Texte, mieux vaut Utiliser Readln effectivement et je suis d'acord que les performances ne sont pas au rendez-vous...

3. Les Stream sont la solution. Commme je vais avoir de nombreux fichiers à analyser dont certains seront assez volumineux, j'ai développé une structure particulière pour mes besoins.

Méthode que je pense adopter :
1. J'ouvre le fichier de travail avec un FileStream 2. Je le copie par bloc dans un memoryStream
(dans le code ci-dessous, un bloc = 1 ligne du fichier)
3. Je procède aux vérifications (ici test de longueur), comptabilité des erreurs constatées et
affichage des progressions et messages

4. Je créée une image du fichier dans un TList afin
pour l'exemple de le trié par ordre alphabétique rapidement

Voilà où j'en suis. ça ne parait pas pas très optimisé. Je vais devoir choisir entre le mémoryStream et la TList me semble t-il. Utiliser les deux parait surfait...

Voici le bout de code actuel:

var
  FS       : TFileStream;
  MSb      : TMemoryStream;
  I        : LongInt;
  fFCount  : Real; // Pour séparation des milliers dans Format
  L,M      : String;
  C        : Char;
  TailleBloc: Integer;
  Ligne    : array [1..12] of char;
begin
  {initialisations locales}
   ...
  {DEBUT TRAITEMENT LONG}
  {1. Transfert des lignes du Fichier dans une TList afin de trier rapidement
      les valeurs du fichier d'origine par ordre alphabétique croissant}
FS := TFileStream.Create(FicTest, fmOpenRead );
TailleBloc := 12;
L  := '';
C  := #0;
For I:=1 to FS.Size div TailleBloc do
Begin
  MSb := TMemoryStream.Create; // Création bloc
  MSb.CopyFrom(FS,TailleBloc); // Copie d'un bloc
  MSb.Position := 0; // Index début de Bloc
  MSb.Read(Ligne,12);
  L := Ligne;
  If not ((Ligne[11] = #13 ) and (Ligne[12] = #10)) then
  begin
    inc(FError);
    FMsgLog := '  - er n°'+InttoStr(FError)+' : '+L;
    Synchronize(AffichageMemoLog);
  end;
  ListLignesFic.Add(L);
  Inc(FCount);
end;
FS.Free;
ListLignesFic.Sort;
fFCount := FCount;
FMsgLog := '  - '+Format('%.0n',[fFCount/1])+' éléments triés';
Synchronize(AffichageMemoLog);
FMessage      := 'Triage du Fichier effectué...';
Synchronize(AfficherMessage);
...
if FError = 0 then
begin
  FMsgLog := 'Vérification longueur des '+inttoStr(FCount)+' enregistrements effectuée';
  Synchronize(AffichageMemoLog);
  FMsgLog := '- Aucune erreur détectée';
  Synchronize(AffichageMemoLog);
end;


Merci pour votre aide.

Jean_Jean
Commenter la réponse de cs_Jean_Jean

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.