CLASSE CTHREAD

cs_laurent1024 Messages postés 987 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 30 août 2012 - 7 mai 2006 à 11:34
Niamorh Messages postés 10 Date d'inscription vendredi 12 novembre 2004 Statut Membre Dernière intervention 23 novembre 2008 - 23 nov. 2008 à 20:21
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/37487-classe-cthread

Niamorh Messages postés 10 Date d'inscription vendredi 12 novembre 2004 Statut Membre Dernière intervention 23 novembre 2008
23 nov. 2008 à 20:21
Salut, c'est intéressant de regarder ta source car j'ai implémenté une classe de thread similaire, modulo quelques détails.

Notamment, la boucle de message est implémentée par ma classe de base. MA classe dérivée ne doit pas implémenter un Run() mais plutôt un OnMessage( Message* ).
Je peux donc créer un thread "inactif" et lui donner du travail via un .PostMessage( Message* ) (méthode de ma classede base, qui s'occupe de l'appel à l'API Win32). Du coup je n'ai nul besoin de méthodes GetHandle ou GetID, l'API est totalement encapsulée.

Si l'envoi d'un message a réussi, il est possible de faire un .Wait() sur le message pour attendre que le thread ait terminé de le traiter. Cela vient en plus du .Wait() de fermeture du thread.

a+
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
10 mars 2008 à 20:59
Bonjour,

Regardes avec les objets thread de la stdlib qu'il serait possible d'encapsuler dans une classe telle que celle-ci.
kobi888 Messages postés 1 Date d'inscription lundi 10 mars 2008 Statut Membre Dernière intervention 10 mars 2008
10 mars 2008 à 15:55
Bonjour!

Classe très utile!!
Tu n'aurais pas d'équivalent sous linux?

merci
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
18 déc. 2007 à 11:01
-->

Il y a quelques autres modifs, je te conseille de re-télécharger le nouveau code.
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
18 déc. 2007 à 11:00
Effectivement, j'avais corrigé ces erreurs mais apparement l'upload du nouveau code ne s'est pas passé correctement.
Voilà qui est fait !

Voici le code correct :
DWORD WINAPI Thread(LPVOID pParam)
{
//appeler la méthode run
((CThread*)pParam)->Run();

return 0;
}
roidelajungle Messages postés 9 Date d'inscription vendredi 5 octobre 2007 Statut Membre Dernière intervention 18 décembre 2007
18 déc. 2007 à 10:27
Salut,

j'essaye d'utiliser cette classe, et lorsque je compile le fichier Thread.cpp Visual C++ me retourne deux erreurs :

error C2065: 'm_hThread' : undeclared identifier
error C2065: 'm_dwThreadId' : undeclared identifier

et il me dit que cela concerne la fin du code dans Thread.cpp :

DWORD WINAPI Thread(LPVOID pParam)
{
//appeler la méthode run
((CThread*)pParam)->Run();

//fin du thread
CloseHandle(m_hThread); // ici
m_hThread = NULL;
m_dwThreadId = 0; // et là

return 0;
}

et je ne sais pas du tout quoi faire, vu que je n'ai modifier ni Thread.h ni Thread.cpp

bobbyantho peux-tu encore une fois éclairer ma lenterne?
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
9 oct. 2006 à 18:05
Très juste, je corrige ça dès que possible.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
9 oct. 2006 à 17:51
private:
HANDLE m_hThread;
DWORD m_dwThreadId;
BOOL m_bActif;

Puisqu'il y a bien:
m_hThread = NULL;
dans le constructeur, m_bActif me semble perdre 4 octets pour rien.
m_hThread jouera parfaitement ce role, non ?
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
1 juil. 2006 à 14:31
Merci !

Essaye plutôt avec la mise à jour que je viens de faire car l'ancienne version comprenait quelques bugs.

Bonnes vacances !
lordskyser1 Messages postés 84 Date d'inscription lundi 31 mars 2003 Statut Membre Dernière intervention 1 juillet 2006
1 juil. 2006 à 12:42
super, merci de te décarcasser autant pour que je puisse comprendre. Aujourd'hui c'est le premier jour des vacances pour moi, mais je vais essayer çà très rapidement :) encore merci, pour la peine je te met 10/10 ^^ continue ainsi c'est parfait
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
30 juin 2006 à 09:24
Rectification, pas de foncteurs ici mais des pointeurs de fonctions !
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
30 juin 2006 à 09:23
Oui, il faut en effet un objet par thread.
Si les threads doivent faire des choses différentes, il faudra créer une classe par tâche à effectuer. Si tu veux par contre appeler seulement des procédures différentes au sein de la même classe, le plus simple est d'utiliser les foncteurs. (je ne sais pas si je suis clair ?).

Un exemple :

//.h
class CMaClasse : public CThread
{
private:
//pointeur sur la procédure à appeler fonction
void (*m_pProc)(void);

public:
//constructeur et destructeur
CMaClasse();
~CMaClasse();

//fonction de sélection de la procédure à appeller
void SelectProc(void CMaClasse::(*pProcedure)(void));

private:
//surcharge de la méthode Run
void Run(void);
//différentes procédures pouvant être appelées par le thread
void Proc1(void);
void Proc2(void);
...
};

//.cpp
#include "MaClasse.h"
CMaClasse::CMaClasse()
{
//initialiser le pointeur à NULL
m_pProc = NULL;
}
CMaClasse::~CMaClasse()
{
}
void SelectProc(void CMaClasse::(*pProcedure)(void))
{
//initialiser le pointeur avec la fonction donnée
m_pProc = pProcedure;
}
void CMaClasse::Run(void)
{
//si une procédure est définie, l'appeler
if(m_pProc)
this->(*m_pProc)();
}

Ensuite, pour l'utiliser, c'est comme dans mon précédent exemple sauf que si l'on veut changer la procédure à appeler, on fait par exemple :

CMaClasse MaClasse1, MaClasse2;

MaClasse1.SelectProc(CMaClasse::Proc1);
MaClasse1.Start();

MaClasse2.SelectProc(CMaClasse::Proc2);
MaClasse2.Start();

Voilà, c'est la solution qui me parait la plus simple.
lordskyser1 Messages postés 84 Date d'inscription lundi 31 mars 2003 Statut Membre Dernière intervention 1 juillet 2006
30 juin 2006 à 08:10
merci, c'est parfait! par contre je vois juste un petit inconvénient : si on veu lancer plusieurs threads qui exécutent des procédures différentes, il faut faire deux classes différentes qui héritent de CThread, c'est çà? est-il possible de passer quelque part (constructeur ou méthode run) en paramètre le nom de la procédure à exécuter afin qu'à partir d'une même classe deux procédures différentes puissent être exécutées dans deux instances différentes?
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
30 juin 2006 à 00:57
Voilà !

Considérons la classe CMaClasse définie comme suit :

//CMaClasse.h
#include "Thread.h"
class CMaClasse : public CThread
{
public:
//constructeur et destructeur
CMaClasse();
~CMaClasse();

private:
//surcharge de la méthode Run
void Run(void);
};

//CMaClasse.cpp
#include "MaClasse.h"
CMaClasse::CMaClasse()
{
}
CMaClasse::~CMaClasse()
{
}
void CMaClasse::Run(void)
{
/*mettre ici le code à éxécuter dans le thread, par exemple pour un serveur TCP */

//tant que le client est connecté
{
//si données recues
{
//interprétation des données
}
}
//déconnexion du client
}

//main.cpp
#include "MaClasse.h"
int main(void)
{
...

//déclarer un objet
CMaClasse MaClasseObj;

//lancer le thread
MaClasseObj.Start();

...

return 0;
}

Voilà, j'espère avoir répondu à ta question. (j'ai fait cette classe ServeurTCP dont je me suis servi pour l'exemple et je la mettrais bientôt sur le site).
lordskyser1 Messages postés 84 Date d'inscription lundi 31 mars 2003 Statut Membre Dernière intervention 1 juillet 2006
29 juin 2006 à 15:09
Félicitation pour cette classe, pourrais tu donner un exmeple de surcharge de Run pour que l'on puisse exécuter la procédure que l'on veut stp?
bobbyantho Messages postés 69 Date d'inscription vendredi 10 octobre 2003 Statut Membre Dernière intervention 23 avril 2009
7 mai 2006 à 11:49
C'est vrai que c'est inutile ici, mais j'ai pris l'habitude d'aussi initialiser mes données membres dans le destructeur à des fins pratiques.
Par exemple, lorsque je surcharge l'opérateur d'affectation(=), j'appelle explicitement le destructeur de la classe qui m'initialise en même temps les données membres.
cs_laurent1024 Messages postés 987 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 30 août 2012 25
7 mai 2006 à 11:34
Classe claire, qui a en plus l'air d'être simple à utiliser. Par contre, il y a un truc que je comprend pas :
CThread::~CThread()
{
//si thread actif
if(m_bActif)
{
//terminer
}
//initialisation
m_hThread = NULL;
m_dwThreadId = 0;
m_bActif = FALSE;
}

-> pourquoi une initilisation à la fin du destructeur ??
Rejoignez-nous