problème de passage de param dans une méthode thread
Le
Nicolas ROBERT
Bonjour,
Le programme suivant ne marche pas comme je le voudrais. Ma classe singleton
MaCLasse a une méthode DemarreTache() qui appelle la methode
FonctionThread() dans un thread, avec la structure T_Param en parametre.
C'est ce passage de parametre qui ne fonctionne pas. Quand je controle les
valeurs de ma structure dans et en dehors de la fonction, ceux -ci
diffèrent. Je ne comprends pas pourquoi. Quelqu'un verrait -il l'erreur que
je n'ai pas vue ?
D'avance merci
Cdt.
//************
declaration
**********/
class MaCLasse{
private:
HANDLE Htache[4]; //Handle de processus
DWORD IdTache[4]; //Identificateur de tache
//Constructeur
Carte();
//destructeur
~Carte();
public:
DlgCtrls *dlgctrls; //structure de la carte Dialogic
static MaCLasse *Instance; //singleton de la classe (instance unique)
//Methode de demarrage de tache
int DemarreTache(int codeTache);
//Methode statique de traitement dans un thread des tache enregistrement
static DWORD WINAPI FonctionThread(LPVOID lparam);
//Creation ou recupration de l'instance unique Carte
static Carte *GetInstance(void){
if(Instance == 0){
Instance=new Carte;
}
return Instance;
}
//Suppression de l'instance unique Carte()
static Kill(){
if(Instance!=0){
delete Instance;
Instance=0;
}
}
};//Fin de la classe Carte
//***********************
Implementation
*************************//
//***
Structure passee en param dans la methode Thread
***/
typedef struct Thread_Param {
MaClasse *MonInstance;
int IdDlgctrls;
char str[25];
int Tache;
char FileRec[25];
}T_Param;
//Fonction qui appelle la methode d'execution de tache dans un thread separe
DWORD WINAPI MaClasse::FonctionThread(LPVOID lparam){
T_Param *tparam=(T_Param *) lparam;
printf("#####ExecuteTache");
printf("Instance: %d",tparam->MonInstance);
printf("str: %s",tparam->str);
printf("File: %s",tparam->FileRec);
printf("Tache: %s",tparam->Tache);
printf("IdDlgCtrls: %s",tparam->IdDlgctrls);
return 1;
}//
int MaCLasse::DemarreTache(int codeTache){
int i;
T_Param paramthread;
printf("DemarreTache()");
for (i=0; i<=4; i++){
paramthread.IdDlgctrls=i;
strcpy(paramthread.str,char avoile);
paramthread.MonInstance=this;
paramthread.Tache=codeTache;
printf("paramthread: %d",paramthread);
//on cree le process avec la structure T_Param en parametre
//Htache[i]=CreateThread(0,0,FonctionThread,(LPVOID)¶mthread,0,&IdTache[
i]);
Htache[i]=CreateThread(0,0,FonctionThread,¶mthread,0,&IdTache[i]);
//Gestion Erreur creation processus
if(Htache[i]==NULL){
return 0;
}
printf("Demarre Tache(): IdTache: %d Htache:
%d",IdTache[i],Htache[i]);
return (int)Htache[i];
}//fin for
}//
Le programme suivant ne marche pas comme je le voudrais. Ma classe singleton
MaCLasse a une méthode DemarreTache() qui appelle la methode
FonctionThread() dans un thread, avec la structure T_Param en parametre.
C'est ce passage de parametre qui ne fonctionne pas. Quand je controle les
valeurs de ma structure dans et en dehors de la fonction, ceux -ci
diffèrent. Je ne comprends pas pourquoi. Quelqu'un verrait -il l'erreur que
je n'ai pas vue ?
D'avance merci
Cdt.
//************
declaration
**********/
class MaCLasse{
private:
HANDLE Htache[4]; //Handle de processus
DWORD IdTache[4]; //Identificateur de tache
//Constructeur
Carte();
//destructeur
~Carte();
public:
DlgCtrls *dlgctrls; //structure de la carte Dialogic
static MaCLasse *Instance; //singleton de la classe (instance unique)
//Methode de demarrage de tache
int DemarreTache(int codeTache);
//Methode statique de traitement dans un thread des tache enregistrement
static DWORD WINAPI FonctionThread(LPVOID lparam);
//Creation ou recupration de l'instance unique Carte
static Carte *GetInstance(void){
if(Instance == 0){
Instance=new Carte;
}
return Instance;
}
//Suppression de l'instance unique Carte()
static Kill(){
if(Instance!=0){
delete Instance;
Instance=0;
}
}
};//Fin de la classe Carte
//***********************
Implementation
*************************//
//***
Structure passee en param dans la methode Thread
***/
typedef struct Thread_Param {
MaClasse *MonInstance;
int IdDlgctrls;
char str[25];
int Tache;
char FileRec[25];
}T_Param;
//Fonction qui appelle la methode d'execution de tache dans un thread separe
DWORD WINAPI MaClasse::FonctionThread(LPVOID lparam){
T_Param *tparam=(T_Param *) lparam;
printf("#####ExecuteTache");
printf("Instance: %d",tparam->MonInstance);
printf("str: %s",tparam->str);
printf("File: %s",tparam->FileRec);
printf("Tache: %s",tparam->Tache);
printf("IdDlgCtrls: %s",tparam->IdDlgctrls);
return 1;
}//
int MaCLasse::DemarreTache(int codeTache){
int i;
T_Param paramthread;
printf("DemarreTache()");
for (i=0; i<=4; i++){
paramthread.IdDlgctrls=i;
strcpy(paramthread.str,char avoile);
paramthread.MonInstance=this;
paramthread.Tache=codeTache;
printf("paramthread: %d",paramthread);
//on cree le process avec la structure T_Param en parametre
//Htache[i]=CreateThread(0,0,FonctionThread,(LPVOID)¶mthread,0,&IdTache[
i]);
Htache[i]=CreateThread(0,0,FonctionThread,¶mthread,0,&IdTache[i]);
//Gestion Erreur creation processus
if(Htache[i]==NULL){
return 0;
}
printf("Demarre Tache(): IdTache: %d Htache:
%d",IdTache[i],Htache[i]);
return (int)Htache[i];
}//fin for
}//

Poser une question


Je réponds vite fait sans me plonger dans ton code : les
paramètres du thread sont dans la pile et peuvent donc
être écrasés quand la fonction retourne, alors que le thread
lancé est en train de d'en servir. Utilise plutôt des données
statiques ou allouées dynamiquement.
--
I have systematically eliminated all references to "software",
because some people disagree about what it means.
--Andrew Suffield
Nicolas ROBERT wraute:
Euh, déjà, c'est assez embrouillé là.
Que font ces constructeurs et destructeurs là ?
Quel est le rapport entre Carte et MaClasse ?
Autant pour moi, Ces destructeurs et constructeurs sont ceux de ma classe
Maclasse qui s'appelle Carte, pour les besoins du post, j'avais changé le
nom de la classe et allégé le contenu des méthodes.
On peut les remplacer par
MaClasse(); et ~MaCLasse();
Selon Nicolas ROBERT:
>> [Snip le code]
Oui, il faut bien sûr 'nettoyer' le code pour le présenter et pour mieux
identifier l'erreur.
Mais votre code ne compile pas. Loin de là.
Par exemple, les constructeurs/destructeurs ne sont pas accessible.
(ils sont en zone privée)
Comment pensez vous initialiser votre classe ?
De plus, il serait profitable d'indiquer comment on utilise cette classe
, ne serait-ce que pour pouvoir reproduire l'erreur.
D'une manière générale, en C++, évitez d'utiliser les "printf" et autres
"strcopy".
Préférez les mécanismes de la bibliothèque standard.
- std::cout et les std::string -
A ce propos, le "strcpy(paramthread.str,char avoile);" est plus que
douteux écrit tel quel.
Vous trouvez aussi des fonctions de formatage
- entre autres choses -
bien pratiques sur boost.org.
classe
le
Les constructeurs et destructeurs sont effectivement en private. Ils sont
utilisés via les méthode MaCLasse::Kill() et MaCLasse::*GetInstance() (cf
1er post).
Pour récupérer l'instance unique de MaCLasse, je fais l'appel suivant:
MaClasse *MonInstanceDeClasse;
MonInstanceDeClasse=MaCLasse::GetInstance();
Cette méthode GetInstance() me retourne mon instance si elle existe, et cree
une nouvelle instance si aucune n'éxiste.
Pour ce qui est du passage de variable, je pense avoir résolu mon pb
(merci M. Leclerc), et déclarant ma structure paramThread en static dans ma
méthode DemarreThread().
Merci donc de votre réactivité.
Cdt
Nicolas