Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1799 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Arrêter une boucle en fonction des actions de l'utilisateur

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Arrêter une boucle en fonction des actions de l'utilisateur

n°830956
deltaden
Posté le 24-08-2004 à 17:03:22  profilanswer
 

Salut,
 
alors, ça a peut-être déjà été traité, mais vu que la fonction recherche est en panne...
 
J'utilise Borland C++ Builder 6. Je fais un soft où l'utilisateur lance une méthode (en cliquant sur un bouton) qui peut durer (très) longtemps. Je voudrais donc avoir la possibilité d'annuler cette exécution.
 
Je vois pas trop comment faire, car il s'agit d'une boucle qui prend quasi 100% du CPU, et l'interface ne réagit plus aux actions.  
 
J'ai essayé de lancer la fonction dans une nouvelle Thread, mais je n'y connais rien et je me suis un peu paumé. J'ai testé _beginThread, ça marche, ça lance le calcul en tâche de fond, mais j'ai pas trouvé comment killer le thread...
 
Merci bcp


Message édité par deltaden le 24-08-2004 à 17:05:49
mood
Publicité
Posté le 24-08-2004 à 17:03:22  profilanswer
 

n°830973
docmaboul
Posté le 24-08-2004 à 17:19:55  profilanswer
 

Il suffit de :
- utiliser une variable partagée entre le thread principal et l'autre thread  
- y coller la valeur qui va bien quand l'utilisateur dit stop
- tester de temps en temps dans le thread de calcul la valeur de la variable et agir en fonction

n°831008
deltaden
Posté le 24-08-2004 à 17:32:49  profilanswer
 

pfff, oui, évidement... comment j'ai pas pensé à ça :??:
 
Merci bien  :jap:

n°831063
bjone
Insert booze to continue
Posté le 24-08-2004 à 18:02:23  profilanswer
 

tu peux aussi mesure à chaque itération de la boucle mesurer depuis combien de temps tu est dans la boucle, et par exemple, toutes les secondes ou 1/4 de seconde aller retraiter la queue des messages.  
 
ça doit être un Application->ProcessMessages(), je sais plus sous C++ Builder.
 
pense aussi, lorsque tu lances un traitement, à inhiber les parties du GUI qui ne doit plus rien déclencher, car si dans ta boucle de traitement tu refais un tour périodiquement dan s la queue des messages, et que le bouton ayant lancé le traitement est recliqué, ton application devrait pêter les plombs.  
 
c'est aussi valable si tu passes par l'approche threadée (qui est potentiellement la meilleure)


Message édité par bjone le 24-08-2004 à 18:03:54
n°831066
deltaden
Posté le 24-08-2004 à 18:08:37  profilanswer
 

Bon, en essayant de donner à _beginThread une fonction membre
de ma classe, ça donne ça:
[C++ Erreur] UnitMain.cpp(298): E2034 Impossible de convertir 'void (* (_closure )(void *))(void *)' en 'void (*)(void *)'
 
Ok, les signatures de méthodes ne correspondent pas...
En sortant ma méthode de ma classe, ça marche, mais c'est un peu laid, je dois donner comme paramètre l'instance de ma classe et accéder à toutes les variables internes.
 
C'est impossible d'appeller de cette manière une méthode appartenant à une classe ?
 
Edit: j'avais pas vu ton message bjone. je vais regarder à ça aussi.


Message édité par deltaden le 24-08-2004 à 18:10:37
n°831074
bjone
Insert booze to continue
Posté le 24-08-2004 à 18:19:03  profilanswer
 

non, d'un point de vue bas niveau, quand une méthode de classe est appellée, elle recoit comme premier paramètre l'adresse de l'instance de classe (le this), comme paramètre implicite. (sauf pour les méthodes statiques)
 
il te faut une fonction "normale" qui appelles la méthode de l'instance qui va bien.
 
généralement quand tu crées un thread, tu as la fonction à appeller, et un paramètre à passer à la fonction.
 
il faut faire un truc du style:
 
class MaClasse
{
public:
    void MaMéthode();
};
 
ThreadFunction( DWORD Valeur ) // Valeur : paramètre passé à la création du thread
{
   MaClasse *Instance=reinterpret_cast<MaClasse *>(Valeur);
   Instance->MaMéthode;
}
 
à la création du thread:
 
MaClasse *MonTruc= ..... ;// ton instance de classe qui contient la méthode à threadifier
 
BeginThread/CreateThread() du style:
 
CreateThread( ThreadFunction, MonTruc ); // ptet à caster.
 
par contre je te dis ptet des bêtes: je raisonne par rapport aux implémétation classque des threads (surtout Win32), pas rapport ptet à ce qu'ils pourraient avoir rajoutés dans C++ Builder (mais tu peux utiliser les API Win32 si tu veux)
 
---
 
tu peux aussi faire une méthode statique, qui elle n'aura pas besoin d'instance:
 
class MaClasse
{
public:
    void MaMéthode();
     
    static void ThreadWrapper( DWORD Value ); // DWORD ou autre suivant le prototype des api de threading que tu utilises
};
 
et au niveau implémentation:
 
MaClasse::ThreadWrapper( DWORD Value )
{
    MaClasse *Instance=reinterpret_cast<MaClasse *>(Value);
     
    Instance->MaMéthode();
}


Message édité par bjone le 24-08-2004 à 18:22:44
n°831091
bjone
Insert booze to continue
Posté le 24-08-2004 à 18:34:42  profilanswer
 

sinon pour arrêter le thread, tu ne le tues pas à la "porc", vue que ne sais pas dans quel état sera tes strutures. (tu ne fais pas un "kill" explicite du thread)
 
mais effectivement, tu utilises un flag (attention il faudra peut être mettre un ou plusieurs sémaphores), et la boucle de MaClasse::MaMéthode() devra être capable de s'arrêter proprement.
 
en sortant de la fonction de Thread, celui ci sera automatiquement supprimmé. (d'ailleurs la fonction de Thread doit retourner quelque chose à regarder dans la doc)

n°831120
Taz
bisounours-codeur
Posté le 24-08-2004 à 19:10:17  profilanswer
 

on y va molo avec les cast sur les instances, sinon ça va partir dans le décor, vous allez rien comprendre

n°831182
deltaden
Posté le 24-08-2004 à 20:48:16  profilanswer
 

ok, merci beaucoup bjone, j'étais arriver à qlqc de fonctionnel, mais pas aussi clair.
 
A priori, le ProcessMessage() est suffisant, je n'ai pas vraiment besoin de faire un second thread.  
De toute façon, même si toute l'interface est inutilisable pendant la mesure, ce n'est pas grave, car pendant cette période elle sert à rien.
Je crois que je vais simplement faire comme ça.
 
Enfin, j'ai appris quelque chose, c'est toujours utile :)


Message édité par deltaden le 24-08-2004 à 20:55:44
n°831200
bjone
Insert booze to continue
Posté le 24-08-2004 à 21:14:11  profilanswer
 

Taz a écrit :

on y va molo avec les cast sur les instances, sinon ça va partir dans le décor, vous allez rien comprendre


 
le reinterpret_cast<> est adapté là non ?
 
(un à l'aller pour passer l'adresse d'un l'instance, et l'un au retour pour récupérer l'adresse de l'instance de manière transparente)


Message édité par bjone le 24-08-2004 à 21:15:00
mood
Publicité
Posté le 24-08-2004 à 21:14:11  profilanswer
 

n°831201
bjone
Insert booze to continue
Posté le 24-08-2004 à 21:16:26  profilanswer
 

deltaden a écrit :

ok, merci beaucoup bjone, j'étais arriver à qlqc de fonctionnel, mais pas aussi clair.
 
A priori, le ProcessMessage() est suffisant, je n'ai pas vraiment besoin de faire un second thread.  
De toute façon, même si toute l'interface est inutilisable pendant la mesure, ce n'est pas grave, car pendant cette période elle sert à rien.
Je crois que je vais simplement faire comme ça.
 
Enfin, j'ai appris quelque chose, c'est toujours utile :)


 
c'est pas tellement la notion d'utilitée ou pas, c'est que si l'utilisateur clique sur le même bouton qui va lancer ton traitement, tu vas avoir deux fois le même traitement sur le même jeu de donné (et un gros blam rapidement)


Message édité par bjone le 24-08-2004 à 21:16:52
n°831206
Taz
bisounours-codeur
Posté le 24-08-2004 à 21:21:04  profilanswer
 

bjone a écrit :

le reinterpret_cast<> est adapté là non ?
 
(un à l'aller pour passer l'adresse d'un l'instance, et l'un au retour pour récupérer l'adresse de l'instance de manière transparente)

static_cast peut suffir si t'es sur de toi.

n°831215
deltaden
Posté le 24-08-2004 à 21:29:36  profilanswer
 

bjone a écrit :

c'est pas tellement la notion d'utilitée ou pas, c'est que si l'utilisateur clique sur le même bouton qui va lancer ton traitement, tu vas avoir deux fois le même traitement sur le même jeu de donné (et un gros blam rapidement)


Je vois pas ce que ça change avec un thread: ça va lancer deux thread identique, ce qui dans mon cas va aussi tout faire planter.
 
De toute façon c'est pas un problème, une fois qu'on lance le traitement, le bouton se transforme en bouton annuler...

n°831264
bjone
Insert booze to continue
Posté le 24-08-2004 à 22:14:10  profilanswer
 

Taz a écrit :

static_cast peut suffir si t'es sur de toi.


 
ok.

n°831265
bjone
Insert booze to continue
Posté le 24-08-2004 à 22:15:25  profilanswer
 

deltaden a écrit :

Je vois pas ce que ça change avec un thread: ça va lancer deux thread identique, ce qui dans mon cas va aussi tout faire planter.
 
De toute façon c'est pas un problème, une fois qu'on lance le traitement, le bouton se transforme en bouton annuler...


 
ha ok, non, je disais juste ça au cas où ton bouton de lancement restait activé, si il passe en annuler et qu'en cliquant dessus ça coupe bien le traitement, c'est bon.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Arrêter une boucle en fonction des actions de l'utilisateur

 

Sujets relatifs
Plantage appli perl/tk lors d'une boucle ?aide fonction qui appel l'événment OnActivate chaque 3 minutes
[c#] Fonction pour la téléphoniefonction ou macro excel
JS: window.onload Comment l'appeler avec 2 fonction /=[Caml] Probleme resolution fonction
SQL fonction conversion vers dateconstruction d'un boucle
question concernant la fonction copy()Problème avec un boucle For Each et une fonction recursive
Plus de sujets relatifs à : Arrêter une boucle en fonction des actions de l'utilisateur


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR