OVH Cloud OVH Cloud

problème de passage de param dans une méthode thread

7 réponses
Avatar
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\n");

printf("Instance: %d",tparam->MonInstance);
printf("str: %s\n",tparam->str);
printf("File: %s\n",tparam->FileRec);
printf("Tache: %s\n",tparam->Tache);
printf("IdDlgCtrls: %s\n",tparam->IdDlgctrls);

return 1;
}//---------------------------

int MaCLasse::DemarreTache(int codeTache){
int i;
T_Param paramthread;
printf("DemarreTache()\n");

for (i=0; i<=4; i++){
paramthread.IdDlgctrls=i;
strcpy(paramthread.str,char avoile);
paramthread.MonInstance=this;
paramthread.Tache=codeTache;

printf("paramthread: %d\n",paramthread);

//on cree le process avec la structure T_Param en parametre

//Htache[i]=CreateThread(0,0,FonctionThread,(LPVOID)&paramthread,0,&IdTache[
i]);
Htache[i]=CreateThread(0,0,FonctionThread,&paramthread,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

}//---------------------------

7 réponses

Avatar
Manuel Leclerc
Nicolas ROBERT a écrit :

Quand je controle les valeurs de ma structure dans
et en dehors de la fonction, ceux -ci diffèrent.

int MaCLasse::DemarreTache(int codeTache){

T_Param paramthread;
CreateThread(0,0,FonctionThread,&paramthread,0,&IdTache[i]);

}



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
Avatar
David MAREC
'lut.
Nicolas ROBERT wraute:


//************
declaration
**********/

class MaCLasse{

private:
HANDLE Htache[4]; //Handle de processus
DWORD IdTache[4]; //Identificateur de tache

//Constructeur
Carte();
//destructeur
~Carte();




Euh, déjà, c'est assez embrouillé là.
Que font ces constructeurs et destructeurs là ?

Quel est le rapport entre Carte et MaClasse ?
Avatar
Nicolas ROBERT
"David MAREC" a écrit dans le message de
news:413da035$0$23303$
'lut.
Nicolas ROBERT wraute:


> //************
> declaration
> **********/
>
> class MaCLasse{
>
> private:
> HANDLE Htache[4]; //Handle de processus
> DWORD IdTache[4]; //Identificateur de tache
>
> //Constructeur
> Carte();
> //destructeur
> ~Carte();


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();
Avatar
David MAREC
Bonjour,

Selon Nicolas ROBERT:

>> [Snip le code]
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.



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.
Avatar
Nicolas ROBERT
>
>> [Snip le code]
>>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.

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.




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
Avatar
Manuel Leclerc
Nicolas ROBERT a écrit :

Pour ce qui est du passage de variable, je pense avoir
résolu mon pb (en déclarant ma structure paramThread
en static dans ma méthode DemarreTache).




Ce qui peut poser un problème si deux appels à DemarreTache
ont lieu coup sur coup. Dans ce cas, plutôt que de s'embêter
à gérer une éventuelle synchronisation, autant faire une
allocation dynamique.

--
<@Logan> I spent a minute looking at my own code by accident.
<@Logan> I was thinking "What the hell is this guy doing?"
Avatar
Nicolas ROBERT
"Manuel Leclerc" a écrit dans le message de
news:
Nicolas ROBERT a écrit :

> Pour ce qui est du passage de variable, je pense avoir
> résolu mon pb (en déclarant ma structure paramThread
> en static dans ma méthode DemarreTache).


Ce qui peut poser un problème si deux appels à DemarreTache
ont lieu coup sur coup. Dans ce cas, plutôt que de s'embêter
à gérer une éventuelle synchronisation, autant faire une
allocation dynamique.



effectivement, je m'en suis rendu compte en faisant les tests.. L'avantage
de la variable statique est qu'elle peut être appelée "par tout le monde",
l'inconvénient est qu'elle peut être appelée "par tout le monde". Je vais
donc suivre tes précieux conseils, et encore merci.


--
<@Logan> I spent a minute looking at my own code by accident.
<@Logan> I was thinking "What the hell is this guy doing?"