Petit probleme de récursivité entre deux appels de sub

Petit probleme de récursivité entre deux appels de sub - VB/VBA/VBS - Programmation

Marsh Posté le 07-12-2005 à 19:08:32    

Bonjour, j'ai un petit souci avec deux subs qui s'appellent mutuellement dans le code ci-dessous. Une erreur de type StackOverflow (Err 28 : Espace de pile insufisant) arrête l'application au bout d'une dizaine de seconde. Connaisseriez vous un appel spécial demandant de terminer sub2 en appelant sub1 afin de permettre de pas accumuler ces fonctions dans la mémoire.
 

Code :
  1. Private Sub Command1_Click()
  2.     sub1
  3. End Sub
  4. Private Sub sub1()
  5.     'Socket envoyant des données
  6.     DoEvents
  7.     Debug.Print "sub1"
  8.     sub2
  9. End Sub
  10. Private Sub sub2()
  11.     'Sub de fin d'envoi des données : envoi de la suite
  12.     DoEvents
  13.     Debug.Print "sub2"
  14.     sub1 'Seulement si il reste des données à envoyer...
  15. End Sub

Reply

Marsh Posté le 07-12-2005 à 19:08:32   

Reply

Marsh Posté le 08-12-2005 à 15:25:32    

Voila un schéma trés simplifié de ce que ça donne dans l'appli complete :
 
Une requete cliente >> appelle une fonction qui lit x octets d'un fichier >> qui l'envoie sur le socket >> qui une fois terminé (socket_complete) >> appel la fonction qui lit x octets d'un fichier >> qui l'envoie sur le socket >>  ....... >> et arrete le tout lorsque la fin du fichier est atteint
 
En clair c'est récursif mais comme dans le bout de code plus haut, le code présent après les appels de sub est ignoré (il reste en attente) et au bout d'un moment la pile déborde... puis c'est le drame!
 
Comment passer d'un appel à l'autre sans accumuler les fonction 'presque' fini initilement en mémoire?

Reply

Marsh Posté le 08-12-2005 à 17:36:06    

Refait tes fonctions pour ne pas faire d'appels réucrsifs


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
Reply

Marsh Posté le 08-12-2005 à 18:36:59    

j'ai oublié comment ca marche vb, mais je verrai ca plutot dans une boulce que comme tu le fais.
 
ouvrir le fichier
lire une ligne
tant qu'on n'est pas à la fin du fichier
{
    envoyer la ligne
    lire une ligne
}

Message cité 1 fois
Message édité par art_dupond le 08-12-2005 à 21:48:47
Reply

Marsh Posté le 08-12-2005 à 21:05:45    

Le problème avec une boucle c'est que sur un long transfert, la boucle doit tourner en permanance en vérifiant si le socket a terminé l'envoi de ce qu'on lui a demandé d'envoyer afin de lire la suite dans le fichier et de l'envoyer au socket.
 
Avant j'avais un timer qui faisait sans problème : socket_complete mettait true à une variable et une fois que le timer passait sur cette variable à true il envoyait la suite, mais c'était terriblement lent pour envoyer des centaines de mo, même a interval de 1ms.

Reply

Marsh Posté le 08-12-2005 à 21:12:24    

art_dupond a écrit :

j'ai oublié comment ca marche vb, mais je verrai ca plutot dans une boulce que comme tu le fais.
 
ouvrir le fichier
lire une ligne
tant qu'on n'est pas à la fin du fichier
{
    envoyer la ligne
    lifre une ligne
}


 
Dans cet exemple sur un fichier de 2go, tout est mis en mémoire et envoyé directement au socket, c'est assez bourrin :d . socket_complete (la fonction événement appelée par le socket à la fin de l'envoi) doit intervenir pour dire quand on peut envoyer la suite, quand il est libre... à moins d'avoir beaucoup de mémoire :d

Reply

Marsh Posté le 08-12-2005 à 21:23:46    

c'est quoi le problème avec la boucle, j'ai pas bien pigé
 
suffit de mettre un DoEvents avant de faire le loop...

Message cité 1 fois
Message édité par Arjuna le 08-12-2005 à 21:25:23
Reply

Marsh Posté le 08-12-2005 à 21:46:33    

Arjuna a écrit :

c'est quoi le problème avec la boucle, j'ai pas bien pigé
 
suffit de mettre un DoEvents avant de faire le loop...


 
oui mais dans ce cas le proc tourne à 99% même avec un doevent (encore pour un seul transfert) alors que dans le cas de subs qui s'appellent il n'y a aucune surcharge du cpu, le seul souci est le dépassement de piles :/

Reply

Marsh Posté le 08-12-2005 à 22:02:16    

un truc comme ca peut etre (me rappelle vraiment pas bien, je ne sais pas si ca marcherait)
 

Code :
  1. lire_x_octets
  2. tant que (pas fin de fichier)
  3. {
  4.    envoi_des_octets
  5.    sortir de la boucle;
  6. continuer:
  7.    lire_x_octets
  8. }
  9. detection_fin_envoi
  10. {
  11.    goto continuer
  12. }


 
 
pas taper si c'est mal :sweat:

Message cité 1 fois
Message édité par art_dupond le 08-12-2005 à 22:02:50
Reply

Marsh Posté le 08-12-2005 à 22:22:50    

art_dupond a écrit :

un truc comme ca peut etre (me rappelle vraiment pas bien, je ne sais pas si ca marcherait)
 

Code :
  1. lire_x_octets
  2. tant que (pas fin de fichier)
  3. {
  4.    envoi_des_octets
  5.    sortir de la boucle;
  6. continuer:
  7.    lire_x_octets
  8. }
  9. detection_fin_envoi
  10. {
  11.    goto continuer
  12. }


 
 
pas taper si c'est mal :sweat:


 
Je ne pense pas qu'il reussisse à revenir dans la boucle juste en faisant un saut de ligne, mais le probleme c'est que ça fait toujours appel à une boucle et donc à une grosse charge cpu (rien que pour un seul transfert). Avec les trois subs qui s'appellent les uns les autres (et qui font un beau dépassement de pile :whistle: ) il n'y a aucune charge cpu.

Reply

Marsh Posté le 08-12-2005 à 22:22:50   

Reply

Marsh Posté le 08-12-2005 à 23:55:35    

comme ca alors ?

Code :
  1. sub1()
  2.    lire_x_octets
  3.    envoi_des_octets
  4. end sub
  5. detection_fin_envoi
  6.    lire_x_octets_suivants
  7.    envoi_des_octets (si pas EOF)
  8. end


 
 
 
sinon tu peux expliquer pourquoi une boucle entraine une grosses charge cpu (c'est une question) ? :jap:  
 
ps: désolé si je propose des bêtes solutions...

Reply

Marsh Posté le 09-12-2005 à 01:21:29    

comme art_dupond : je suis perplexe quant à la charge de 100% à cause de la boucle...
 
m'enfin le plus simple serait peut-être simplement de passer à un autre langage pour écrire une DLL qui s'occupe des transfert si vraiment ça marche pas.

Reply

Marsh Posté le 09-12-2005 à 01:41:02    

art_dupond a écrit :

comme ca alors ?

Code :
  1. sub1()
  2.    lire_x_octets
  3.    envoi_des_octets
  4. end sub
  5. detection_fin_envoi
  6.    lire_x_octets_suivants
  7.    envoi_des_octets (si pas EOF)
  8. end


 
sinon tu peux expliquer pourquoi une boucle entraine une grosses charge cpu (c'est une question) ? :jap:  
 
ps: désolé si je propose des bêtes solutions...


 
c'est pas des solutions bêtes et merci déjà de répondre :d
 
on parle peut être pas du même type de boucle :
 
une boucle :
 

Code :
  1. do while reste_octets
  2.   if socket_a_fini_lenvoi then
  3.     lire_xx_nouveaux_octets
  4.     envoyer_xx_nouveaux_octets
  5.   end if
  6.   doevents
  7. loop


 
me pompe 99% de mon cpu pendant qu'elle tourne, d'ailleur une boucle while contenant qu'un doevents : idem :/

Reply

Marsh Posté le 09-12-2005 à 10:43:19    

fils_de_la_lumiere a écrit :

oui mais dans ce cas le proc tourne à 99% même avec un doevent (encore pour un seul transfert) alors que dans le cas de subs qui s'appellent il n'y a aucune surcharge du cpu, le seul souci est le dépassement de piles :/


Quand tu fais une boucle avec un doevents, le CPU est indiqué comme étant utilisé à 100% mais ça ne gène pas l'execution des autres programmes.


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
Reply

Marsh Posté le 09-12-2005 à 10:46:16    

tu t'en fout de ça. ça bouffe 100% du CPU, mais c'est de la charge qui ne consomme pas si je puis dire. seul "doevents" fait quelquechose dans cette boucle, hors il laisse la place aux autres processus si besoin. donc que le CPU soit à 100% ou 0%, la dispoibilité du cpu reste la même pour les autres programmes.

Reply

Marsh Posté le 09-12-2005 à 18:54:55    

Moi quand je fait une boucle avec un doevents tout seul au bout d'un moment ça se ressent sur la température de mon cpu. Je connais pas de programme utilisant 99% du cpu (même fictivement) rien que pour transférer un fichier à 5ko/sec :d Je trouve pas ça trés clean de tester en permanence si une condition est remplie pour continuer à envoyer des données (c'est pourtant ce que je faisais avec un timer mais avec une boucle c'est encore moins clean). Je pense que le socket doit avertir activement (comme dans l'exemple du deuxième poste) du fait qu'il ait fini d'envoyé en appelant de lui même une sub et non passivement (la fin d'envoi met une variable à true sur lequel une boucle ou timer fait un test discontinue).

Reply

Marsh Posté le 09-12-2005 à 20:04:37    

pour ça, il faut coder multithread, mais VBS ne le permet pas (VB non plus d'ailleurs)
 
Seul truc que tu peux faire, comme je t'ai dit, c'est utiliser une DLL écrite dans un autre langage, qui elle s'occuper de threader le tranfsert, et ne te redonne la main que lorsqu'elle a terminé (ou alors tu la laisse tourner en tâche de fond, et tu la butte quand tu t'apperçois qu'elle a fini, mais c'est un peu plus compliqué à faire)

Reply

Sujets relatifs:

Leave a Replay

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