Comment arréter une boucle dans une autre fonction...(+clair ci-dessou

Comment arréter une boucle dans une autre fonction...(+clair ci-dessou - C++ - Programmation

Marsh Posté le 28-04-2003 à 23:05:08    

Bon voila, j'ai un prog avec le MFC
J'ai declaré un bouton "demarrer", il fait parti de la classe acquisit
 
En fait en cliquant sur ce bouton, je lance une fonction à l'interieur de laquelle s'execute une boucle while avec pour parametre (par ex) :  
while(m_intMavariable!=1)
{code}
 
dans la meme classe j'ai mis un bouton "arretter",
lorsqu'on clique dessus :  
void acquisit::OnButtonArreter
{m_intMavariable=1;}
 
je voudrais arreter le while de tout à l'heure, mais ça ne marche pas;  
j'ai declaré m_intMavariable en variable globale, ma fonction de tout à l'heure retourne un entier et est déclaré en globale aussi;
mais ça ne marche pas, vous avez une idée???

Reply

Marsh Posté le 28-04-2003 à 23:05:08   

Reply

Marsh Posté le 29-04-2003 à 00:12:05    

Tu ne peux pas arreter une boucle while comme ca (a moins de faire une espece de gestion d'interuption). Pendant l'execution de la boucle while le programme sera insensible à ton evenement bouton et ta variable ne seras pas modifiée.
 
A mon avis pour que ca marche, il faut lancer deux threads separés, un pour l'aquisition et l'autre pour catcher l'evemement associé au bouton.

Reply

Marsh Posté le 29-04-2003 à 00:18:51    

pendant que tu est dans ta boucle while, ton programme est uniquement dans ta boucle while et ne peut pas gérer le click sur le bouton.
La solution propre consiste a utiliser des threads, mais on peut bidouiller un truc.
 
Il faut dire au programme que tu veux prendre en compte les messages (click, mouvement de la souris ...) pendant que tu est dans ta boucle while, il faut demander à ton appli de traiter les messages qui lui arrivent.
 
y a un début de solution ici :
http://msdn.microsoft.com/library/ [...] essing.asp

Reply

Marsh Posté le 29-04-2003 à 00:20:44    

fykman a écrit :

Tu ne peux pas arreter une boucle while comme ca (a moins de faire une espece de gestion d'interuption). Pendant l'execution de la boucle while le programme sera insensible à ton evenement bouton et ta variable ne seras pas modifiée.
 
A mon avis pour que ca marche, il faut lancer deux threads separés, un pour l'aquisition et l'autre pour catcher l'evemement associé au bouton.


 
Et comment je peux faire ce petit miracle ;-) ???
Parce que moi et le MFC, on est pas copain depuis très longtemps;
à vrai dire j'ai beaucoup de mal à m'en servir, vu que mon seul prof, c'est moi!!! ...

Reply

Marsh Posté le 29-04-2003 à 00:22:34    

SquiZz a écrit :

pendant que tu est dans ta boucle while, ton programme est uniquement dans ta boucle while et ne peut pas gérer le click sur le bouton.
La solution propre consiste a utiliser des threads, mais on peut bidouiller un truc.
 
Il faut dire au programme que tu veux prendre en compte les messages (click, mouvement de la souris ...) pendant que tu est dans ta boucle while, il faut demander à ton appli de traiter les messages qui lui arrivent.
 
y a un début de solution ici :
http://msdn.microsoft.com/library/ [...] essing.asp


 
ok; je vais voir ça! :jap:

Reply

Marsh Posté le 29-04-2003 à 00:25:59    

j'ai codé un petit exemple rapide,
tu crées une appli MFC dialog
tu ajoutes deux boutons et tu mets ca comme code pour le click sur les boutons :

Code :
  1. void CLongoperationDlg::OnButton1()
  2. {
  3. // TODO: Add your control notification handler code here
  4. m_loop = true;
  5. MSG msg;
  6. while(m_loop)
  7. {
  8.  Sleep(100);
  9.  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  10.  {
  11.  TranslateMessage(&msg);
  12.  DispatchMessage(&msg);
  13.  }
  14. }
  15. AfxMessageBox("fin de la boucle" );
  16. }
  17. void CLongoperationDlg::OnButton2()
  18. {
  19. // TODO: Add your control notification handler code here
  20. m_loop = false;
  21. }


 
m_loop c'est une variable membre bool de la classe de ton dialog .
et 'oila cappucino
 
[edit] c'est pas très propre mais ca marche.


Message édité par SquiZZ le 29-04-2003 à 00:27:26
Reply

Marsh Posté le 29-04-2003 à 00:29:57    

SquiZz a écrit :

j'ai codé un petit exemple rapide,
tu crées une appli MFC dialog
tu ajoutes deux boutons et tu mets ca comme code pour le click sur les boutons :

Code :
  1. void CLongoperationDlg::OnButton1()
  2. {
  3. // TODO: Add your control notification handler code here
  4. m_loop = true;
  5. MSG msg;
  6. while(m_loop)
  7. {
  8.  Sleep(100);
  9.  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  10.  {
  11.  TranslateMessage(&msg);
  12.  DispatchMessage(&msg);
  13.  }
  14. }
  15. AfxMessageBox("fin de la boucle" );
  16. }
  17. void CLongoperationDlg::OnButton2()
  18. {
  19. // TODO: Add your control notification handler code here
  20. m_loop = false;
  21. }


 
m_loop c'est une variable membre bool de la classe de ton dialog .
et 'oila cappucino
 
[edit] c'est pas très propre mais ca marche.
 


 
 
Danke schön!!! :jap:  :jap:  :jap:  
(de toute façon la propreté c'est pas mon fort!!!! :-) :lol: )

Reply

Marsh Posté le 29-04-2003 à 00:31:14    


 
C'est bien ce que je disait, il faut deux threads ....  :)  

Reply

Marsh Posté le 29-04-2003 à 00:32:21    

fykman a écrit :


 
C'est bien ce que je disait, il faut deux threads ....  :)  
 


 
hé hé, perdu !

Reply

Marsh Posté le 29-04-2003 à 15:38:22    

Bon en fait j'ai un gros probleme, lorsque je lance mon prog,
la fonction que j'ai cité ci-dessus, merde à mort :  
soit elle se lance et la plus moyen de rien faire,
soit elle ne se lance pas et rien ne se passe!!
donc la je vais mettre un peu de code pour que ce soit plus clair (
 
 
 
//ma fonction //
 
 int
SegmentorCallback( PSEGMENTOR_DATA pData)
{
   assert( pData != (PSEGMENTOR_DATA)NULL );
 
   /* Write segmentor scene data to an 8-bit pgm file */
 
   COLOUR_IMAGE *pClrImage = &pData->scene_colour_image; //on pointe sur l'adresse des données de l'image
 
   
   static int image_no = 0;
   m_bLoop=true;
 
    //on fait l'acquisition de 100 images, possibilité de le régler aussi (bouton stop)
   
 MSG msg;
 while(m_bLoop)  
  {  
   Sleep(10);      
   while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
    {  
      TranslateMessage(&msg);
      DispatchMessage(&msg);
       }  
       
         
     
   char filename[50],filename1[50],filename2[50],filename3[50],filename4[50],filename5[50];
    unsigned int image[120][160];
 
*/etc etc /*
 
 
   fclose(pf2);
 }
  AfxMessageBox("fin de la boucle" );   //pour le repérage
   return 1;
 
 }
 
 
 
 
mon bouton demarrer
 
void CAcquisitionV1Dlg::OnButtonDemar()  
{
 // TODO: Add your control notification handler code here
 
 CENSYS_INSTANCE cinstance;
   CENSYS_ERROR err;
 
*/code ......../*
L'appel de ma fonction
  err = censysSystemSetSegmentorCallback( cinstance, SegmentorCallback );
 
 
*/code......./*
 
 
 
 
 
 
 
censysSystemSetSegmentorCallback se trouve dans un fichier censys.h que j'ai inclu dans mon projet
 
declaration de censysSystemSetSegmentorCallback [#00f00e]
 
CENSYS_API CENSYS_ERROR
censysSystemSetSegmentorCallback(
     CENSYS_INSTANCE           ciInstance,
     CENSYS_SEGMENTOR_CALLBACK cscCallbackFunction
     );
 
 
avec [#f00e00]typedef void* CENSYS_INSTANCE;

typedef int CENSYS_SEGMENTOR_CALLBACK( PSEGMENTOR_DATA pData );
 
Si vous comprenez quelque chose, HELP!!!
 
 

Reply

Marsh Posté le 29-04-2003 à 15:38:22   

Reply

Marsh Posté le 29-04-2003 à 22:55:39    

Desolé pour les couleurs, je pensais pas que ça serait aussi laid!!!
Sinon un petit up!
 
 
 
 
 
 
 
 
 
 
 
 
 
 :??:  :??:  :??:  :??:  :??:  :??:  
brouillard, mon joli brouillard, où suis je???
:lol:     [:quetzalcoalt]->int *projet de merde

Reply

Marsh Posté le 29-04-2003 à 22:56:06    

Desolé pour les couleurs, je pensais pas que ça serait aussi laid!!!
Sinon un petit up!
 
 
 
 
 
 
 
 
 
 
 
 
 
 :??:  :??:  :??:  :??:  :??:  :??:  
brouillard, mon joli brouillard, où suis je???
  [:quetzalcoalt]->int *projet de merde

Reply

Marsh Posté le 30-04-2003 à 02:40:20    

SquiZz a écrit :


 
c'est pas très propre mais ca marche.
 


 
ouais, c'est degueulasse et ca marche pas.
 
Bravo pour le code fouettant, mettre un TranslateMessage() dans un handler, faut le faire... Apres l'autre il s'etonne ke ca marche mal...
 
Effectivement pour faire un minimum propre il faut un thread supplémentaire (un seul, pas 2 ou 3).
 
Si j'ai tout compris ce ke tu voulais, une solution est :
 - dans le handler du bouton demarrer, tu crée un thread ki éxécutera ton code.
 - dans le handler du bouton arreter, tu signale au thread qu'il faiut qu'il évite.
 
ah bah voila, c tout en fait.
 
apres, je te repondrais bien "fais man CreateThread", mais chuis dans une bonne heure, donc voila un bout de code rapide :
 

Code :
  1. bool gl_bBordel;
  2. HANDLE gl_hThread;
  3. DWORD WINAPI Thread_Truc(LPVOID lpParameter)
  4. {
  5. while (gl_bBordel)
  6. {
  7.  // ton bordel
  8. }
  9. return 1;
  10. }
  11. LRESULT Handler_BoutonDemarrer(UINT uMsg, WPARAM wParam, LPARAM lParam)
  12. {
  13. DWORD dw;
  14. gl_bBordel = true;
  15. gl_hThread = CreateThread(NULL, 0, Thread_Truc, NULL, 0, &dw);
  16. return 0;
  17. }
  18. LRESULT Handler_BoutonArreter(UINT uMsg, WPARAM wParam, LPARAM lParam)
  19. {
  20. gl_bBordel = false; // Solution pas trop crade mais ki peut rater si tu rates du code du thread
  21. TerminateThread(); // Solution bien crade mais ki rate pas
  22. return 0;
  23. }


 
voila.
j'ai rien testé, et j'espere meme ke ca marche pas, histoire ke ca te fasse penser un minimum.
 
pour le handler du bouton arreter, t'as le choix entre 2 méthodes : la 1ere si tu veux gerer tout bien au risque ke ca continue du code pendant un peu de temps (le temps ke ca arrive au while), ou bien "fo ke ca s'arrete maintenant, tant pis pour ma ram".
 
si t'utilises des classes, t'auras le droit d'éviter les globales.
 
.

Reply

Marsh Posté le 30-04-2003 à 02:49:13    

et il est ou le WaitForSingleObject(), hein???
 
au lieu de faire un while() avec un booleen global, on fait un

Code :
  1. while (WaitForSingleObject(hEvent, 500) != WAIT_OBJECT_O)
  2. {
  3. // blabla
  4. }


 
Tu me decois Konar... C un peu faible tout ca.

Reply

Marsh Posté le 30-04-2003 à 03:03:59    

konar_spreme a écrit :

et il est ou le WaitForSingleObject(), hein???
 
au lieu de faire un while() avec un booleen global, on fait un

Code :
  1. while (WaitForSingleObject(hEvent, 500) != WAIT_OBJECT_O)
  2. {
  3. // blabla
  4. }


 
Tu me decois Konar... C un peu faible tout ca.
 


 
ouais mais la ca va te repondre : c koi hEvent ? c koi WaitForSingleObject ? c koi le C++ ? c koi blabla ?

Reply

Marsh Posté le 30-04-2003 à 03:10:21    

Konar a écrit :


 
ouais mais la ca va te repondre : c koi hEvent ? c koi WaitForSingleObject ? c koi le C++ ? c koi blabla ?
 


 
Oui ms la je peux pas aider, c sur...
Je fais deja de l aide handicapé toute la journée, vais pas en faire le soir en plus.
 
Tiens ca t'apprendra. :bounce:

Reply

Marsh Posté le 30-04-2003 à 08:00:58    

Konar a écrit :


 
ouais, c'est degueulasse et ca marche pas.
 


 
ouep, mais j'ai trouvé ca dans le msdn :
http://msdn.microsoft.com/library/ [...] essing.asp
 
citation :
"PeekMessage Elsewhere in Your Application
 
Another method for performing idle processing in an application involves embedding a message loop in one of your functions"
 
ensuite on voit un exemple qui utilise pumpmessage.
 
autre citation :
"Although PumpMessage is undocumented, you can examine its source code in the ThrdCore.Cpp file in MFC\Src relative to your Visual C++ installation."
 
et si on va voir le code de pumpmessage, ca fait un pretranslate et un dispatchmessage.
 
Donc ma solution :
1 - est pas très propre
2 - marche pas trop mal
3 - est décrite dans le MSDN

Reply

Marsh Posté le 30-04-2003 à 17:26:49    

Konar a écrit :


 
ouais, c'est degueulasse et ca marche pas.
 
Bravo pour le code fouettant, mettre un TranslateMessage() dans un handler, faut le faire... Apres l'autre il s'etonne ke ca marche mal...
 
Effectivement pour faire un minimum propre il faut un thread supplémentaire (un seul, pas 2 ou 3).
 
Si j'ai tout compris ce ke tu voulais, une solution est :
 - dans le handler du bouton demarrer, tu crée un thread ki éxécutera ton code.
 - dans le handler du bouton arreter, tu signale au thread qu'il faiut qu'il évite.
 
ah bah voila, c tout en fait.
 
apres, je te repondrais bien "fais man CreateThread", mais chuis dans une bonne heure, donc voila un bout de code rapide :
 

Code :
  1. bool gl_bBordel;
  2. HANDLE gl_hThread;
  3. DWORD WINAPI Thread_Truc(LPVOID lpParameter)
  4. {
  5. while (gl_bBordel)
  6. {
  7.  // ton bordel
  8. }
  9. return 1;
  10. }
  11. LRESULT Handler_BoutonDemarrer(UINT uMsg, WPARAM wParam, LPARAM lParam)
  12. {
  13. DWORD dw;
  14. gl_bBordel = true;
  15. gl_hThread = CreateThread(NULL, 0, Thread_Truc, NULL, 0, &dw);
  16. return 0;
  17. }
  18. LRESULT Handler_BoutonArreter(UINT uMsg, WPARAM wParam, LPARAM lParam)
  19. {
  20. gl_bBordel = false; // Solution pas trop crade mais ki peut rater si tu rates du code du thread
  21. TerminateThread(); // Solution bien crade mais ki rate pas
  22. return 0;
  23. }


 
voila.
j'ai rien testé, et j'espere meme ke ca marche pas, histoire ke ca te fasse penser un minimum.
 
pour le handler du bouton arreter, t'as le choix entre 2 méthodes : la 1ere si tu veux gerer tout bien au risque ke ca continue du code pendant un peu de temps (le temps ke ca arrive au while), ou bien "fo ke ca s'arrete maintenant, tant pis pour ma ram".
 
si t'utilises des classes, t'auras le droit d'éviter les globales.
 
.


 
Oki, je vais zieuter ça, merci! :bounce:  :hello:

Reply

Marsh Posté le 01-05-2003 à 20:34:29    

Konar a écrit :


 
ouais, c'est degueulasse et ca marche pas.
 
Bravo pour le code fouettant, mettre un TranslateMessage() dans un handler, faut le faire... Apres l'autre il s'etonne ke ca marche mal...
 
Effectivement pour faire un minimum propre il faut un thread supplémentaire (un seul, pas 2 ou 3).
 
Si j'ai tout compris ce ke tu voulais, une solution est :
 - dans le handler du bouton demarrer, tu crée un thread ki éxécutera ton code.
 - dans le handler du bouton arreter, tu signale au thread qu'il faiut qu'il évite.
 
ah bah voila, c tout en fait.
 
apres, je te repondrais bien "fais man CreateThread", mais chuis dans une bonne heure, donc voila un bout de code rapide :
 

Code :
  1. bool gl_bBordel;
  2. HANDLE gl_hThread;
  3. DWORD WINAPI Thread_Truc(LPVOID lpParameter)
  4. {
  5. while (gl_bBordel)
  6. {
  7.  // ton bordel
  8. }
  9. return 1;
  10. }
  11. LRESULT Handler_BoutonDemarrer(UINT uMsg, WPARAM wParam, LPARAM lParam)
  12. {
  13. DWORD dw;
  14. gl_bBordel = true;
  15. gl_hThread = CreateThread(NULL, 0, Thread_Truc, NULL, 0, &dw);
  16. return 0;
  17. }
  18. LRESULT Handler_BoutonArreter(UINT uMsg, WPARAM wParam, LPARAM lParam)
  19. {
  20. gl_bBordel = false; // Solution pas trop crade mais ki peut rater si tu rates du code du thread
  21. TerminateThread(); // Solution bien crade mais ki rate pas
  22. return 0;
  23. }


 
voila.
j'ai rien testé, et j'espere meme ke ca marche pas, histoire ke ca te fasse penser un minimum.
 
pour le handler du bouton arreter, t'as le choix entre 2 méthodes : la 1ere si tu veux gerer tout bien au risque ke ca continue du code pendant un peu de temps (le temps ke ca arrive au while), ou bien "fo ke ca s'arrete maintenant, tant pis pour ma ram".
 
si t'utilises des classes, t'auras le droit d'éviter les globales.
 
.


 
Bon en fait, je n'arrive pas à me servir de ce que tu as dit;
J'ai donc fait une recherche sur WaitForSingleObject,
j'ai trouvé ça : www.codeppc.com/evc/articles/multithread/mt1.htm
 
LE problème est que quand mettre un thread sur ma fonction, je ne peux plus passer en parametre les parmatres de ma fonction
 
ma fonction :
 int SegmentorCallBack(PSEGMENTOR_DATA pData)
{
  while (WaitForSingleObject     //je sais que ca n'a pas de   sens la mais c'est pour le reperage
{code}
code
}
 
J'ai testé ça :
declaration  
DWORD WINAPI SegmentorCallBack(LPVOID p,PSEGMENTOR_DATA pData)
 
 
ensuite ma fonction
DWORD WINAPI SegmentorCallBack(LPVOID p,PSEGMENTOR_DATA pData)
{
code...
  while (WaitForSingleObject     //je sais que ca n'a pas de   sens la mais c'est pour le reperage
{code}
code
}
 
mais bon, ça passe pas trop,
Alors comment je peux passer en paramètre PSEGMENTOR_DATA pData????

Reply

Marsh Posté le 01-05-2003 à 20:43:01    

Le lpParameter te permet de faire passer tous les parametres dont tu as besoin.
 
Exemple :

Code :
  1. typedef struct s_Truc
  2. {
  3. int i;
  4. PSEGMENTOR_DATA pData;
  5. } t_Truc;
  6. DWORD WINAPI Thread_Truc(LPVOID lpParameter)
  7. {
  8. t_Truc *Truc = (t_Truc*)lpParameter;
  9. // ton code...
  10. }
  11. // Puis pour l'appel de CreateThread :
  12. {
  13. t_Truc *Truc = new t_Truc;
  14. // Init de Truc
  15. CreateThread(NULL, 0, Thread_Truc, (LPVOID)Truc, 0, &dw);
  16. }


 
sinon oublie le WaitForSingleObject pour le moment...


Message édité par Konar le 01-05-2003 à 20:53:28
Reply

Marsh Posté le 01-05-2003 à 20:50:59    

Konar a écrit :

Le lpParameter te permet de faire passer tous les parametres dont tu as besoin.
 
Exemple :
 
typedef struct s_Truc
{
 int i;
 PSEGMENTOR_DATA pData;
} t_Truc;
 

Code :
  1. DWORD WINAPI Thread_Truc(LPVOID lpParameter)
  2. {
  3. t_Truc *Truc = (t_Truc*)lpParameter;
  4. // ton code...
  5. }
  6. // Puis pour l'appel de CreateThread :
  7. {
  8. t_Truc *Truc = new t_Truc;
  9. // Init de Truc
  10. CreateThread(NULL, 0, Thread_Truc, (LPVOID)Truc, 0, &dw);
  11. }
  12. sinon oublie le WaitForSingleObject pour le moment...




 
Alala , konar toujours à ma rescousse!!
merci!
I go to test that!!! :hello:

Reply

Marsh Posté le 02-05-2003 à 16:18:03    

sbbtn a écrit :


 
Alala , konar toujours à ma rescousse!!
merci!
I go to test that!!! :hello:  


Bon ça ne marche pas non plus, le gros probleme est que je n'arrive pas à changer la declaration de ma fonction;
la en gros , tu me dit que je dois declarer ma fonction en tant que DWORD WINAPI SegmentorCalllBack(LPVOID lpParameter)
 
ok  je veux bien,
je l'ai fait, j'ai fait aussi une structure (t_Truc....) avec mes variables;
mais lorsque je veux lancer ma new fonction
 
 
err=CensysSystemSetSegmentorCallback(cinstance /*on s'en fout*/ , SegmentorCalllBack);
 
J'ai une erreur de type:
 
error C2664: 'censysSystemSetSegmentorCallback' : impossible de convertir le paramètre 2 de 'DWORD (LPVOID)' en 'CENSYS_SEGMENTOR_CALLBACK (__cdecl *)'
 
 
J'ai essayé de modifier les types de chaque parametre mais ça n'a pas marcher.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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