Plantage appli perl/tk lors d'une boucle ?

Plantage appli perl/tk lors d'une boucle ? - Perl - Programmation

Marsh Posté le 24-08-2004 à 11:27:51    

bonjour,
 
je fait une appli en perl:tk sous windows.
Dans cette appli, j'ai une boucle qui attend la creation d'un fichier texte. Cependant, lors de cette boucle, mon appli tk plante (je n'ai pas la main).
je debute en perl et je ne vois pas trop comment eviter ce probleme.
merci

Code :
  1. do{
  2.       $texte="Attente";
  3.       $message -> configure ( -text => $texte ) ;
  4. }
  5. until( not -z "result.txt" ) ;


 

Reply

Marsh Posté le 24-08-2004 à 11:27:51   

Reply

Marsh Posté le 24-08-2004 à 14:18:37    

si tu boucle tu ne laisse plus Tk gerer ses evenements (rafraichissement, etc...)
 
bon deja dans ta boucle tu n'a pas à remettre le texte en permanance, il te suffit de trouner dans le vide:

Code :
  1. $message->configure(-text => "Attente" );
  2. 1 while ( -z "result.txt" );
  3. $message->configure(-text => "Ok" );


 
ensuite si tu faix ca tu va utiliser 100% de ton CPU à tourner comme un fou pour pas grand chose. Donc tu peux deja ajouter des petites pauses:

Code :
  1. $message->configure(-text => "Attente" );
  2. while ( -z "result.txt" ) {
  3. select(undef,undef,undef, 0.01);
  4. }
  5. $message->configure(-text => "Ok" );


 
le select(undef,undef,undef, 0.01) va simplement faire une pause de 0.01 seconde
 
ensuite il faudrait que tu permete à Tk de gerer ses evenements pendant que tu boucle:
 

Code :
  1. # $mw = fenetre principale
  2. $message->configure(-text => "Attente" );
  3. while ( -z "result.txt" ) {
  4. select(undef,undef,undef, 0.01);
  5. $mw->update;
  6. }
  7. $message->configure(-text => "Ok" );


 
et ensuite, le fin du fin serais de ne pas avoir de boucle mais de demander à Tk de gerer cette attente lui meme, avec ses timer:
 

Code :
  1. # $mw = fenetre principale
  2. $message->configure(-text => "Attente" );
  3. my $timer;
  4. # toutes les 100ms, ca doit deja largement suffire
  5. $timer = $mw->repeat(100, sub{
  6. if (not -z "result.txt" ) { # ou if -s...
  7.  $timer->cancel; # on cancel le timer pour ne plus qu'il tourne
  8.  $message->configure(-text => "Ok" );
  9.  ...
  10. }
  11. });

Reply

Marsh Posté le 24-08-2004 à 14:30:17    

mais bon dans tous les cas cette solution n'est pas nonplus optimale car la commande -z (stat en fait) est bloquante: si le fichier se trouve sur un support tres lent (genre disquette) alors ca risque de bloquer qq instant à chaque fois (mais rien à voir avec ton probleme actuel, je te rassure). Dans ce cas il faudrait utiliser la fonction filevent de Tk, mais elle est assez foireuse (surtout sous Windows). Le problème c'est que les operations sur le systeme de fichiers sont toujours synchrones.
Si tu es sous Linux tu peux toujours utiliser la fonction aio_stat de Linux::AIO...
Enfin bon je pense pas que ce soit vraiment ce dont tu a besoin nonplus!
 
Enfin pour le fun:
 

Code :
  1. use Linux::AIO;
  2. $message->configure(-text => "Attente" );
  3. wait_size("result.txt", \&fichier_ok);
  4. sub wait_size {
  5. my ($fichier, $cb) = @_;
  6. aio_stat($fichier, sub{
  7.  if (-z _) {
  8.   $mw->after(100, [\&wait_size, $fichier, $cb]);
  9.  } else {
  10.   $cb->($fichier);
  11.  }
  12. });
  13. }
  14. sub fichier_ok {
  15. my $fichier = shift;
  16. $message->configure(-text => "Ok" );
  17. ...
  18. }


Message édité par pospos le 24-08-2004 à 14:31:52
Reply

Marsh Posté le 24-08-2004 à 15:48:40    

j'suis en admiration devant tant d'attention....:love:
 
j'ai essayé tes solutions (sauf la dernère je suis sur windows).
la 3ème :

Code :
  1. # $mw = fenetre principale
  2.   $message->configure(-text => "Attente" );
  3.   while ( -z "result.txt" ) {
  4.      select(undef,undef,undef, 0.01);
  5.      $mw->update;
  6.   }
  7.   $message->configure(-text => "Ok" );


est la meilleure, la dernière avec le repeat ne marche pas?? :??:  
c pas super fluide mais c correct
merci

Reply

Marsh Posté le 24-08-2004 à 16:42:35    

bizarre que la version avec le timer ne marche pas...
j'ai pas testé mais dans le principe ca doit fonctionner (et c'est la meilleur solution)
 
sinon pour la solution avec le select, si tu veux un truc plus fluide met 0.001 à la place de 0.01, mais ca risque de mettre ton system de fichier sur els rotules (c'est d'ailleurs sans doute deja pour ca que ca rame, donc ca changera rien)
 
Donc le mieux c'est de faire moins de tests sur le fichier, par exemple seulement une fois sur 100, tout en bouclant plus souvent:
 

Code :
  1. # $mw = fenetre principale 
  2. $message->configure(-text => "Attente" ); 
  3. my $i=0;
  4. for(;;) {
  5. unless (++$i%100) {
  6.  # test le fichier toutes les 100*0.001 = 0.1 secondes
  7.  last unless -z "result.txt";
  8. }
  9. $mw->update;
  10. select(undef,undef,undef, 0.001);
  11. $message->configure(-text => "Ok" );


 
si tu peux meme tester le fichier encore moins souvent (genre ++$i%500 pour 0.5s) ca sera encore mieux
 
mais bon, ca vaut pas un vrai timer Tk

Reply

Marsh Posté le 24-08-2004 à 17:37:02    

tu as raison, le timer marche très bien.
en fait l'erreur vient de moi, je me suis trompé de problème. :pt1cable:  
je croyais que c'etait l'attente d'un fichier qui buggait mon appli, en fait non...
j'execute juste avant l'attente de ce fichier un exe qui prend beaucoup de temps.je croyais que cette execution etait indépendante de mon appli perl/tk.
donc le pb existe toujours... :(
je remet donc le pgr avec l'executable.  

Code :
  1. print `pgr.exe $a $b $c >result.txt `  ;
  2.           while (-z "result.txt" ) {
  3.                        select(undef,undef,undef, 1);
  4.                        $fenetre->update;
  5.                 };


l'exe prg.exe dure de 20s a 5min et c bien lui qui fait planter l'appli.
si tu vois une solution ca m'interesse. :sarcastic:  

Reply

Marsh Posté le 24-08-2004 à 17:48:20    

ha ouai, un programme externe c'est plus chiant...
tu peux utiliser la commande system(1,...)
 
c'est une version non documenté de 'system' (et qui marche peut etre que sous activePerl, mais comme j'imagine que c'est ce que tu utilise tout va bien)
 
en fait c'est un 'system' non bloquant: il lance un processus independant (utilisant la meme console)
 
donc tu fais simplement:
system(1, "pgr.exe $a $b $c >result.txt" );
while...
 
mais pour le select met tout de meme autre chose que 1s, sinon il ne rafraichira la fenetre Tk que une fois par seconde. pour l'instant tu ne le vois pas car l'execution de l'exe bloque et le fichier result.txt est remplie kand ca ne bloque plus, mais avec system(1,...) il faudra effectivement que tu attende que le fichier se remplisse (avec le timer)

Reply

Marsh Posté le 25-08-2004 à 11:57:37    

salut,
c bon c'etait bien ca.
je te remercie
a+

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed