cs_laurent1024
Messages postés987Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention30 août 2012
-
7 mai 2006 à 11:34
Niamorh
Messages postés10Date d'inscriptionvendredi 12 novembre 2004StatutMembreDernière intervention23 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.
Niamorh
Messages postés10Date d'inscriptionvendredi 12 novembre 2004StatutMembreDernière intervention23 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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és1Date d'inscriptionlundi 10 mars 2008StatutMembreDernière intervention10 mars 2008 10 mars 2008 à 15:55
Bonjour!
Classe très utile!!
Tu n'aurais pas d'équivalent sous linux?
merci
bobbyantho
Messages postés69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és9Date d'inscriptionvendredi 5 octobre 2007StatutMembreDernière intervention18 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 :
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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és84Date d'inscriptionlundi 31 mars 2003StatutMembreDerniè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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 avril 2009 30 juin 2006 à 09:24
Rectification, pas de foncteurs ici mais des pointeurs de fonctions !
bobbyantho
Messages postés69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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 :
Voilà, c'est la solution qui me parait la plus simple.
lordskyser1
Messages postés84Date d'inscriptionlundi 31 mars 2003StatutMembreDerniè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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és84Date d'inscriptionlundi 31 mars 2003StatutMembreDerniè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és69Date d'inscriptionvendredi 10 octobre 2003StatutMembreDernière intervention23 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és987Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention30 août 201225 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 ??
23 nov. 2008 à 20:21
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+
10 mars 2008 à 20:59
Regardes avec les objets thread de la stdlib qu'il serait possible d'encapsuler dans une classe telle que celle-ci.
10 mars 2008 à 15:55
Classe très utile!!
Tu n'aurais pas d'équivalent sous linux?
merci
18 déc. 2007 à 11:01
Il y a quelques autres modifs, je te conseille de re-télécharger le nouveau code.
18 déc. 2007 à 11:00
Voilà qui est fait !
Voici le code correct :
DWORD WINAPI Thread(LPVOID pParam)
{
//appeler la méthode run
((CThread*)pParam)->Run();
return 0;
}
18 déc. 2007 à 10:27
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?
9 oct. 2006 à 18:05
9 oct. 2006 à 17:51
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 ?
1 juil. 2006 à 14:31
Essaye plutôt avec la mise à jour que je viens de faire car l'ancienne version comprenait quelques bugs.
Bonnes vacances !
1 juil. 2006 à 12:42
30 juin 2006 à 09:24
30 juin 2006 à 09:23
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.
30 juin 2006 à 08:10
30 juin 2006 à 00:57
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).
29 juin 2006 à 15:09
7 mai 2006 à 11:49
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.
7 mai 2006 à 11:34
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 ??