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

Windows Discussion :

WaitForSingleObject dans des classes héritées


Sujet :

Windows

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2004
    Messages : 33
    Points : 26
    Points
    26
    Par défaut WaitForSingleObject dans des classes héritées
    Bonjour,

    J'essaie de synchroniser 3 threads de lecture et écriture sur un bus CAN et j'ai des petits problèmes.

    Mes trois classes dérivent d'une classe ThreadClass qui offre, enfin qui essaie d'offrir plutôt en ce moment, des méthodes de synchronisation. Mon but est d'avoir des threads qui se comporte de la manière suivante :

    - les 2 threads d'écritures peuvent à tout moment envoyer un message sur le bus et se bloquent après chaque écriture
    - le thread de lecture vérifie toutes les x ms si quelque chose est présent sur le bus et si c'est le cas libère le thread pour lequel la réponse est adressée

    Les méthodes que j'ai créé pour sont les suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void ThreadClass::WaitOne()
    {
        ResetEvent(hEvent);
        WaitForSingleObject(hEvent,INFINITE);
    }
    
    void ThreadClass::Set()
    {
        SetEvent(hEvent);
    }
    hEvent est déclaré dans ThreadClass en protected et initialisé dans les constructeurs des classes dérivées de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    hEvent = CreateEvent(NULL,FALSE,FALSE,"EventMotor");
    Lorsque j'ai un seul thread d'écriture actif tout se déroule sans aucun problème mais dès que je démarre le 2ème plus rien ne fonctionne. J'ai l'impression que les deux threads d'écriture se bloquent sur le même évènement. Ils ne se déroulent que les deux en même temps mais si j'en bloque un ils se bloquent les deux.

    Que fais-je donc de faux ?

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce que tu fais de faux: Tu utilises le même Event nommé.

    Solution: Utiliser des Events anonymes à la place: Il suffit de ne pas leur donner de nom.
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2004
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    C'était pas précisé mais j'utilise bien des noms différents pour mes évènements, c'est d'ailleurs pour ça que je les initialise dans la classe héritée.

    J'ai aussi essayé en leur passant null pour le nom mais rien à faire j'ai le même comportement.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ton event est bien une variable non-statique, hein ?

    Peux-tu poster plus de code ?
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2004
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    Non elle n'est pas statique.
    Pour ma classe mère je me suis basé sur un exemple que j'ai trouvé je ne sais plus où sur Internet auquel j'ai rajouté l'évènement et les deux méthodes ci-dessus.

    ThreadClass.h
    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
    #pragma once
    
    #include <windows.h>
    
    #define WM_STOPTHREAD WM_USER
    
    //Support class used to handle threads.
    class ThreadClass
    {
    	public:
    		enum Priorite
    		{
    			Basse = THREAD_PRIORITY_LOWEST,
    			Normale = THREAD_PRIORITY_NORMAL,
    			Critique = THREAD_PRIORITY_TIME_CRITICAL,
    			TempsReel = REALTIME_PRIORITY_CLASS
    		}Priorite;
    
    	private:
    		HANDLE m_hThread;
    		DWORD m_dwThreadId;
    
    		//thread
    		friend DWORD WINAPI Thread(LPVOID pParam);
    
    
    	protected:
    		//fonction virtuelle appelée par le thread
    		virtual void Run(void) = 0;
                    HANDLE hEvent;
    
    	public:
    		//constructeur
    		ThreadClass();
    		//destructeur
    		virtual ~ThreadClass();
    
    		//lancer le thread
    		void Start(void);
    		//arrêter le thread
    		void Stop(void);
    		//terminer le thread (brutal)
    		void Terminer(void);
    		//changer la priorité
    		void SetPriorite(int iPriorite) const;
    		//retourne l'activité du thread
    		BOOL IsAlive(void) const;
    		//retourne le handle du thread
    		HANDLE GetHandle(void) const;
    		//modifie le handle du thread
    		void SetHandle(HANDLE h);
    		//retourne l'identifiant du thread
    		DWORD GetID(void) const;
    		//modifie l'identifiant du thread
    		void SetID(DWORD id);
    
    		void WaitOne();
    		void Set();
    
    		//attend la fin du thread
    		DWORD Wait(DWORD dwTimeOut) const;
    };
    ThreadClass.cpp
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    #include "ThreadClass.h"
    
    ThreadClass::ThreadClass()
    {
    	//initialisation
    	m_hThread = NULL;
    	m_dwThreadId = 0;
    }
    
    ThreadClass::~ThreadClass()
    {
    	//terminer le thread
    	this->Terminer();
    }
    
    void ThreadClass::Start(void)
    {
    	//si thread non actif
    	if(!m_hThread)
    		//création du thread
    		m_hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,(LPVOID)this,0,&m_dwThreadId);
    }
    
    void ThreadClass::Stop(void)
    {
    	//si thread actif
    	if(m_hThread)
    	{
    		//stop
    		PostThreadMessage(m_dwThreadId,WM_STOPTHREAD,0,0);
    		this->Wait(INFINITE);
    		//initialisation
    		CloseHandle(m_hThread);
    		m_hThread = NULL;
    		m_dwThreadId = 0;
    	}
    }
    
    void ThreadClass::Terminer(void)
    {
    	//si thread actif
    	if(m_hThread)
    	{
    		//terminer
    		TerminateThread(m_hThread,0);
    		CloseHandle(m_hThread);
    	}
    	//initialisation
    	m_hThread = NULL;
    	m_dwThreadId = 0;
    }
    
    void ThreadClass::SetPriorite(int iPriorite) const
    {
    	//si le thread a été déclaré
    	if(m_hThread)
    		//changer la priorité
    		SetThreadPriority(m_hThread,iPriorite);
    }
    
    BOOL ThreadClass::IsAlive(void) const
    {
    	return (m_hThread!=NULL);
    }
    
    HANDLE ThreadClass::GetHandle(void) const
    {
    	return m_hThread;
    }
    
    void ThreadClass::SetHandle(HANDLE h)
    {
        m_hThread = h;
    }
    
    
    DWORD ThreadClass::GetID(void) const
    {
    	return m_dwThreadId;
    }
    
    void ThreadClass::SetID(DWORD id)
    {
        m_dwThreadId = id;
    }
    
    DWORD ThreadClass::Wait(DWORD dwTimeOut) const
    {
    	return WaitForSingleObject(m_hThread,dwTimeOut);
    }
    
    DWORD WINAPI Thread(LPVOID pParam)
    {
    	//appeler la méthode run
    	((ThreadClass*)pParam)->Run();
    
    	//fin du thread
    	CloseHandle(((ThreadClass*)pParam)->GetHandle());
    	((ThreadClass*)pParam)->SetHandle(NULL);
    	((ThreadClass*)pParam)->SetID(0);
    
    	return 0;
    }
    
    void ThreadClass::WaitOne()
    {
        ResetEvent(hEvent);
        WaitForSingleObject(hEvent,INFINITE);
    }
    
    void ThreadClass::Set()
    {
        SetEvent(hEvent);
    }
    Je dérive donc de cette classe pour les 3 que j'utilise pour la communication.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Hum...
    En fait, c'est surtout voir comment tu attends l'event d'un autre thread qui serait intéressant...
    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.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2004
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    Alors pour mes deux classes d'écriture j'ai une méthode MessageReturn de la forme suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void ManagementMotor::MessageReturn(CanMessage * message)
    {
        //Traitement du message reçu
        Set();
    }
    Du côté de la lecture j'appelle la méthode MessageReturn du bon objet suivant le type de message reçu. Concrètement j'ai un switch sur l'id du message et suivant quel périphérique me l'a envoyé je le transmets à l'objet qui s'en occupe.

    Au niveau de l'envoi d'un message j'ai des méthodes de la forme suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CanBusInterface::SendMessage(message);
    WaitOne();

Discussions similaires

  1. [C#]Remonter des événements dans des classes imbriquées
    Par Kcirtap dans le forum Windows Forms
    Réponses: 9
    Dernier message: 14/12/2013, 12h43
  2. distribution d'elements dans des classes
    Par christine1985 dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 31/08/2006, 11h15
  3. Liens entre des classes héritées
    Par qwiqwi dans le forum C++
    Réponses: 12
    Dernier message: 09/02/2006, 15h36
  4. [WSDL][Axis] Récupération de valeur dans des classes java
    Par cosmos38240 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 09/01/2006, 17h38
  5. Réponses: 2
    Dernier message: 04/12/2005, 21h10

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