IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

Conseils sur le thread


Sujet :

MFC

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre �m�rite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    D�tails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par d�faut Conseils sur le thread
    Bonjour � tous, je dois �crire du code avec des threads et ma faible exp�rience dans ce domaine me pousse � venir demander conseil avant.

    Voici ce que je dois faire...

    Lorsque j'instancie mon objet, cr�ez un thread.
    Dans ce thread, v�rifier quelquechose � interval r�gulier.
    A la destruction de l'objet, arretez le thread.
    Dans l'arret du thread, faire une s�rie de choses (style fermeture de fichier).

    Et voici comment je vois les choses, j'esp�re ne pas faire de grosses erreurs et j'espere avoir l'avis de programeur rod�s � ce genre de manipulations.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    // maclasse.h
    #pragma once
    #include "maclasseabstraite.h"
     
    class CMaClasse :
    	public CMaClasseAbstraite
    {
    public:
    	CMaClasse();
    	~CMaClasse(VOID);
     
    private:
    	HANDLE _thread;
    	BOOL _continue;
     
    	static DWORD WINAPI MaFonctionThread(LPVOID p);
    };
     
    // maclasse.cpp
    #include "StdAfx.h"
    #include "maclasse.h"
     
    CRITICAL_SECTION CriticalSection;
     
    CMaClasse::CMaClasse()
    {
    	_continue = TRUE;
    	InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400);
    	_thread = CreateThread(NULL, 0, MaFonctionThread, this, 0, NULL);
    }
     
    CMaClasse::~CMaClasse(VOID)
    {
    	EnterCriticalSection(&CriticalSection);
    	_continue = FALSE;
    	LeaveCriticalSection(&CriticalSection);
     
    	WaitForSingleObject(_thread, 2000);
    	CloseHandle(_thread);
     
    	DeleteCriticalSection(&CriticalSection);
    }
     
    DWORD WINAPI CMaClasse::MaFonctionThread(LPVOID p)
    {
    	CMaClasse *pThis = reinterpret_cast<CMaClasse*>(p);
     
    	EnterCriticalSection(&CriticalSection);
    	while (pThis->_continue)
    	{
    		// Do your job
    		Sleep(1000);
    	}
    	LeaveCriticalSection(&CriticalSection);
     
    	return(0);
    }
    Merci de votre lecture!

  2. #2
    Expert �minent
    Avatar de M�dinoc
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par d�faut
    C'est pas mal, mais:
    1) D�care ton bool�en en volatile, �a vaut mieux
    2) D�place ta section critique dans le thread, car l�, il la garde en continu ---> �a d�bouchera sur une "�treinte fatale".

    D'ailleurs, sous Win32, l'affectation d'une variable 32bits est atomique: Tu n'est pas oblig� d'utiliser un objet de synchronisation.
    Mais si tu tiens � en utiliser un, utilise un Event � la place du bool�en: CreateEvent() dans le constructeur, SetEvent() pour quitter le thread, qui regarde avec WaitForMultipleObject(hEvent, 0); entre chaque Sleep()
    (Sans oublier le CloseHandle() qui va avec dans le destructeur).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parl� avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre �m�rite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    D�tails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par d�faut
    Merci pour ces conseils. Pour le point 1, une explication suppl�mentaire me ferait du bien. Enfin, le "�a vaut mieux" m'interp�le... :-)

    Sinon, j'ai modifi� le code de cette fa�on. Ai-je bien compris o� tu voulais en venir?

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    // maclasse.h 
    #pragma once 
    #include "maclasseabstraite.h" 
     
    class CMaClasse : 
       public CMaClasseAbstraite 
    { 
    public: 
       CMaClasse(); 
       ~CMaClasse(VOID); 
     
    private: 
       HANDLE _thread; 
       //BOOL _continue;
       HANDLE _threadMustQuit;
     
       static DWORD WINAPI MaFonctionThread(LPVOID p); 
    }; 
     
    // maclasse.cpp 
    #include "StdAfx.h" 
    #include "maclasse.h" 
     
    CRITICAL_SECTION CriticalSection; 
     
    CMaClasse::CMaClasse() 
    { 
       //_continue = TRUE;
       _threadMustQuit = CreateEvent(NULL, FALSE, FALSE, NULL);
       InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400); 
       _thread = CreateThread(NULL, 0, MaFonctionThread, this, 0, NULL); 
    } 
     
    CMaClasse::~CMaClasse(VOID) 
    { 
    	 /*
       EnterCriticalSection(&CriticalSection); 
       _continue = FALSE; 
       LeaveCriticalSection(&CriticalSection); 
       */
       SetEvent(_threadMustQuit);
     
       WaitForSingleObject(_thread, 2000); 
       CloseHandle(_thread); 
       CloseHandle(_threadMustQuit);
     
       DeleteCriticalSection(&CriticalSection); 
    } 
     
    DWORD WINAPI CMaClasse::MaFonctionThread(LPVOID p) 
    { 
       CMaClasse *pThis = reinterpret_cast<CMaClasse*>(p); 
       BOOL mustContinue = TRUE;
     
       //EnterCriticalSection(&CriticalSection); 
       //while (pThis->_continue) 
       while (mustContinue) 
       { 
          Sleep(1000);
     
          EnterCriticalSection(&CriticalSection);
          // Do your job
          LeaveCriticalSection(&CriticalSection); 
     
          if (WaitForMultipleObject(_threadMustQuit, 0) == WAIT_OBJECT_0) mustContinue = FALSE;
       } 
       //LeaveCriticalSection(&CriticalSection); 
     
       return(0); 
    }

  4. #4
    Expert �minent
    Avatar de M�dinoc
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par d�faut
    H� bien, ton code m'a l'air parfait, sauf qu'ici, la CRITICAL_SECTION interne ne sert pas � grand chose, puisque seuls la classe et le thread y auront acc�s.

    Dans ce cas, soit tu la vires compl�tement, soit tu la rends utile en d�veloppant un accesseur qui retourne son adresse (ou mieux, directement des m�thodes enter(), tryEnter() et leave())

    Pour le coup du volatile, je pense que c'est la doc de microsoft qui parle le mieux:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/key_s-z_10.asp
    The volatile keyword is a type qualifier used to declare that an object can be modified in the program by something other than statements, such as the operating system, the hardware, or a concurrently executing thread.
    Bref, �a indique au compilo qu'un autre thread peut le modifier � tout moment.
    Sinon, l'optimiseur peut te virer un test dans une boucle, en le consid�rant toujours faux.
    Par exemple, imagine cette boucle, avec bQuit modifi� par un autre thread pour dire � ce thread-ci de quitter:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    while( bQuit == FALSE )
    	{
    	Sleep(1000);
    	}
    Si bQuit n'est pas d�clar� volatile, le compilo risque de transformer ta Boucle en l'�quivalent de ceci:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    if(bQuit == FALSE)
    	{
    	while( TRUE )
    		{
    		Sleep(1000);
    		}
    	}
    Ce qui sera une boucle infinie...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parl� avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre �clair�
    Homme Profil pro
    D�veloppeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 49
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par d�faut
    J'ai tres recement fais une chose d'assez similaire et comme toi j'ai plong� dans les m�andres du multithreading. M�dinoc m'a d'ailleur bien aid� (mais ne m'avait pas parl� des volatiles le vilain ! ).

    Vu ce que tu veux faire, je dois te mettre en garde d'une chose. Plus tu aura d'instances de thread, plus ca va etre chaud � gerer, le multithread a debugger, c'est tout simplement l'horreur.

    Alors question : as tu vraiment besoin que chaque object ai un thread qui s'execute constamment? (tout depend du nombre d'objet instanciable).

    Plus tu en aura plus tes threads seront "fragment�s" en un sens, et donc, plus le resultat tardera � venir et/ou viendra un peu quand il veut...

    La technique que j'ai employ� de mon cot�, ca a �t� de mettre en place un compteur de reference, un thread static � la classe, et un timer.

    Lorsque le premier objet est instanci�, on lance le thread qui ressemble au tient et on lance un timer qui toutes les n milliseconde reveille ce thread. Et ce thread en fonction du compteur de r�f�rence va faire sa v�rif sur tous les objets instanci�s.

    l'avantage de ce systeme, c'est que tu n'a plus que 3 threads : celui de l'appli, celui du timer, et celui du thread de v�rif. Et sur ce thread de v�rif, tu lui met la priorit� que tu veux.

    voici en gros ce que ca donne (je te passe la partie constructeur, et compteur de ref):

    header :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class CXC64IOmodule
    {
    	private:
    //Les statiques
    	static unsigned short s_usObjectCount;			//nbr d'objets instanciés
     
    	static HANDLE s_htTrigGlobalgrab;				//Handle du thread qui check tous les Inputs
    	static HANDLE s_hTimer;							//Timer pour la fonction InputsListener()
    	static HANDLE s_hTimerQueue;					//Timerqueue pour la fonction InputsListener()
     
    static DWORD WINAPI InputsListener(LPVOID lpParameter);
    static DWORD WINAPI TrigGrabber(LPVOID lpParameter);
     
    	static BOOL s_bRunThreadInputsListener;			//Flag controlant la sortie du thread nommé.
    	static HANDLE s_heventTopTimer;					//Evenement envoyé par le timer toutes les n Millisecondes.
     
     
    	HANDLE LaunchInputsListener(DWORD period, UINT priority= THREAD_PRIORITY_HIGHEST);  //Lance une routine qui va cycliquement metre a jour l'etat des input (tableau Input) attributs : Periode du timer en millisecondes, priorité du thread.
    	void StopInputsListener();
    };
     
    //Threads
     
     
    void CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired);

    le fichier source:


    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    void CXC64IOmodule::StopInputsListener()
    {
    	//On fait ce que tu as mis dans ton code pour arretter les threads
    }
     
    HANDLE CXC64IOmodule::LaunchInputsListener(DWORD period, UINT priority)
    {
    	s_bRunThreadInputsListener=TRUE;
    	if(!s_heventTopTimer)s_heventTopTimer=CreateEvent(NULL,FALSE,FALSE,NULL);
    	ResetEvent(s_heventTopTimer); //Le thread va donc immediatement se mettre en someil et sera reveillé par le timer
    	if(!s_htTrigGlobalgrab)s_htTrigGlobalgrab=CreateThread(NULL,0,&InputsListener,&priority,0,NULL); //On le lance
    	//On crée maintenant le timer
    	s_hTimerQueue = CreateTimerQueue();
    	if (!s_hTimerQueue) AfxMessageBox("Probleme de Creation du timer");
    	CreateTimerQueueTimer(&s_hTimer, s_hTimerQueue, TimerRoutine, NULL , 0, period, WT_EXECUTEINTIMERTHREAD);
     
    	return s_htTrigGlobalgrab;
    }
     
    //////////////////////////////////////TIMER///////////////////////////////////////////
     
    void CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
    {
    	SetEvent(CXC64IOmodule::s_heventTopTimer);
    	return;
    }
     
    //////////////////////////////////////THREADS/////////////////////////////////////////
     
    DWORD WINAPI CXC64IOmodule::InputsListener(LPVOID lpParameter)
    {
    	unsigned int i=0;
    	UINT* priority = (UINT*)  lpParameter;
     
    	SetThreadPriority(GetCurrentThread(),*priority);
    	//Tant qu'on ne demande pas au thread de sortir
    	while(s_bRunThreadInputsListener)
    	{
    		//On attends le top du timer
    		WaitForSingleObject(s_heventTopTimer,INFINITE);
     
    		//Pour toutes les pins d'input
    		for(i=0 ; i< s_usObjectCount ; i++)
    		{
    			//Fait ce qu'il a a faire sur chaque objet			
    		}
    	}
    	return 0L;
    }
    Dans ton cas, LaunchInputListener serait appell� par le constructeur si s_usObjectCount ==1. Et StopInputsListener par le destructeur quand s_usObjectCount atteinds 0.

    voila comme tu vois dans mon code je n'utilise pas de volatile, ca sera corrig� aussitot revenu au boulot

    Pour info avec cette technique, j'arrive � syncroniser des evenement avec 5 ms de tol�rence !!! mon thread est en priorit� RealTime, et je n'ai aucun effet de bord du style pc fig� puisque ce thread dors la pluspart du temps et s'execute en moins de 10 millisecondes.

  6. #6
    Membre �m�rite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    D�tails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par d�faut
    Merci pour vos r�ponses!

    Pour r�pondre rapidement aux questions: je n'aurai qu'une seule instance de cet objet, donc pas trop de souci pour le thread.

    Pour ce qui est de "volatile" c'est exactement ce que j'avais lu � son sujet, mais la doc disant pouvant etre modifi� par l'operating system, je n'ai pas jug� bon de l'utiliser. Quoi qu'il en soit, je travail maintenant avec un �v�nement donc ceci ne s'applique plus � mon probl�me.

    Par contre, ma critical section est encore n�cessaire, en effet, je ne l'avais pas mis dans le code source pour ne pas surcharger le post, mais j'acc�de a des variables au sein de mon objet dans les 2 threads en meme temps.

    Je vais devoir impl�menter un second thread, celui-ci ne se cr�ant pas syst�matiquement au d�marrage. Et l�, une nouvelle question apparait...

    Dans le thread principal, je cr�e le nouveau thread pour qu'il fasse son boulot. Comment puis-je savoir, sans bloquer le thread principal, que le thread de travail est termin� (afin de faire un CloseHandle)? Dois je avoir un timer qui le v�rifie r�guli�rement?

Discussions similaires

  1. Conseil sur l'application et gestion d'un thread
    Par Karl Marx dans le forum Threads & Processus
    R�ponses: 4
    Dernier message: 24/02/2014, 16h30
  2. Conseil sur les thread dans une dll
    Par ksoft dans le forum C
    R�ponses: 2
    Dernier message: 30/03/2009, 15h12
  3. Besoin d'explications et de conseils sur les threads
    Par matteli dans le forum D�veloppement 2D, 3D et Jeux
    R�ponses: 12
    Dernier message: 02/03/2008, 17h27
  4. Recherche Livre / Conseils sur la conception de Base
    Par Yeuma dans le forum D�cisions SGBD
    R�ponses: 7
    Dernier message: 02/01/2004, 14h25
  5. Question simple sur les threads :)
    Par momox dans le forum C++Builder
    R�ponses: 2
    Dernier message: 15/06/2003, 04h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo