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 :

Problème de thread et temps CPU


Sujet :

MFC

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 147
    Par défaut Problème de thread et temps CPU
    Bonjour,

    Mon problème est le suivant :
    J'ai un programme (MFC) qui fait des calculs assez lourd et qui consomment pas mal de temps CPU.
    Or j'ai besoin d'afficher un état de mes calculs au travers de voyant (CStatic avec 2 bitmaps que je switch quand nécessaire).

    Le problème vient de l'affichage de ces voyants qui ne se rafraichissent pas.

    J'ai fait un thread avec la classe CWinThread qui gère le toggle des voyants.
    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
     
    CMyClass::CMyClass()
    {
    	m_NbEvent = 0;
    	m_MyEvent = NULL;
    	m_bStatus=THR_STOPPED;					// Thread arreté
    }
     
    CMyClass::~CMyClass()
    {
    	if (m_MyEvent ) {
    		for (int EvtI = 0 ; EvtI < m_NbEvent ; EvtI++)
    			CloseHandle(m_MyEvent[EvtI]);
    		delete m_MyEvent;
    	}
    }
     
    void CMyClass::ToggleBitmap(int nIndex)
    {
    	::SetEvent(m_MyEvent[nIndex]);
    }
     
    void CMyClass::SetNbEvent(int iMaxEvent)
    {
    	m_NbEvent = iMaxEvent;
    	m_MyEvent = new HANDLE[m_NbEvent];
    	for (int EvtI = 0 ; EvtI < m_NbEvent ; EvtI++)
    		m_MyEvent[EvtI] = CreateEvent(NULL, FALSE, FALSE, NULL);
    }
     
    BOOL CMyClass::InitInstance()
    {
    	m_bStatus= THR_RUNNING;
    	DWORD Ret;
    	int nEvent;
     
    	// Debut boucle principale
    	while (m_bStatus==THR_RUNNING) {
     
    		Ret = ::WaitForMultipleObjects(m_NbEvent, m_MyEvent , FALSE, INFINITE);
    		nEvent = Ret - WAIT_OBJECT_0;
    		::ResetEvent(m_MyEvent[nEvent]);
     
    		if (m_MainDlg) {
    			if (m_MainDlg->m_cLight[nEvent])
    				m_MainDlg->m_cLight[nEvent]->SetBitmap(m_MainDlg->m_bGreen);
    		}
    	};
    	m_bStatus= THR_STOPPED;
    	while (m_bStatus!=THR_STOPPED_ACK) Sleep (2000);
     
    	return TRUE;
    }
    Le thread est créé avec une priorité normale (par défaut).

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Franchement, ce que je conseillerais, ce serait réduire la priorité du thread de travail.

    Et peut-être aussi, éviter d'utiliser une attente bloquante dans ton thread d'UI. Pourquoi ne pas plutôt le prévenir avec un PostMessage() (asynchrone) ou un SendMessage() (synchrone) ?
    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 confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 147
    Par défaut
    Je ne peux pas réduire la priorité du thread de travail car c'est du quasi temps réel.
    Il me semblait que le PostMessage n'est possible qu'avec une fenêtre, me trompe-je ?

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Ça n'est possible que vers une fenêtre, mais ton thread d'UI est supposé en avoir une, ou ça ne serait pas un thread d'UI.

    Déjà, rien qu'un CStatic, c'est déjà une fenêtre.
    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
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Quelques remarques :
    1/ Comment sors-tu de la boucle ? m_bStatus est modifiée ailleurs? Alors il te faudrait peut être vérifié l'accès concurrent (Mutex, section critique).
    2/ Ton thread dérive de CWinThread ? Normalement, tu ne devrais pas faire tout le boulot dans InitInstance mais comme dans le thread principal.
    3/ Ta gestion de la fin du thread (while (m_bStatus!=THR_STOPPED_ACK) Sleep (2000); ) est limite. Tu devrais utiliser un mécanisme de synchronisation spécifique pour terminer ton thread (un évènement de fin de thread par expl).
    4/ Normalement, il n'est pas recommandé d'échanger des MFC entre les threads mais d'échanger leur handle. Donc si m_MainDlg est l'instance créé dans le thread principal, alors tu devrais plutôt échanger le HWND et faire ensuite un CWnd::FromHandle ou CWnd::FromHandlePermanent.
    5/Post/SendMessage prennent en paramètre un HWND. Mais rien n'empêche de créer une fenêtre 'boîte aux lettres' : Message-Only Windows.
    5 bis/ Pour rappel, le comportement de SendMessage entre thread différents est un peu tordu.
    6/ C'est le thread de travail qui pianote sur le tableau d'évènements? Pourquoi avoir fait un thread séparé du thread principal? Tu pouvais rester en écoute dans le thread principale avec MsgWaitForMultipleObjectsEx ? Ou alors faire du 'polling' dans OnIdle?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 147
    Par défaut
    Ce que je ne comprend pas c'est pourquoi les évènements qui sont levés ne débloque pas le WaitForMultipleObjects ? En fait c'est uniquement à la fin de mes calculs qu'ils font effet.

    Citation Envoyé par Médinoc Voir le message
    Ça n'est possible que vers une fenêtre, mais ton thread d'UI est supposé en avoir une, ou ça ne serait pas un thread d'UI.

    Déjà, rien qu'un CStatic, c'est déjà une fenêtre.
    Qu'est ce que tu entend par thread d'UI, est ce que c'est le thread principal ?

    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Quelques remarques :
    1/ Comment sors-tu de la boucle ? m_bStatus est modifiée ailleurs? Alors il te faudrait peut être vérifié l'accès concurrent (Mutex, section critique).
    Pour la sortie du thread j'ai pas mis tout le code, mais je suis à peu prés sur de mon coup.

    Citation Envoyé par 3DArchi Voir le message
    2/ Ton thread dérive de CWinThread ? Normalement, tu ne devrais pas faire tout le boulot dans InitInstance mais comme dans le thread principal.
    Tout à fait exact, d'ailleurs je l'ai déplacé dans Run.

    Citation Envoyé par 3DArchi Voir le message
    3/ Ta gestion de la fin du thread (while (m_bStatus!=THR_STOPPED_ACK) Sleep (2000); ) est limite. Tu devrais utiliser un mécanisme de synchronisation spécifique pour terminer ton thread (un évènement de fin de thread par expl).
    J'ai créé le thread en AutoDelete (et franchement cette partie vient d'un copier coller du code d'un collègue et je suis pas un expert).

    Citation Envoyé par 3DArchi Voir le message
    4/ Normalement, il n'est pas recommandé d'échanger des MFC entre les threads mais d'échanger leur handle. Donc si m_MainDlg est l'instance créé dans le thread principal, alors tu devrais plutôt échanger le HWND et faire ensuite un CWnd::FromHandle ou CWnd::FromHandlePermanent.
    m_MainDlg est le pointeur sur ma CDialog.


    Citation Envoyé par 3DArchi Voir le message
    5/Post/SendMessage prennent en paramètre un HWND. Mais rien n'empêche de créer une fenêtre 'boîte aux lettres' : Message-Only Windows.
    5 bis/ Pour rappel, le comportement de SendMessage entre thread différents est un peu tordu.
    Je ne savais pas.

    Citation Envoyé par 3DArchi Voir le message
    6/ C'est le thread de travail qui pianote sur le tableau d'évènements? Pourquoi avoir fait un thread séparé du thread principal? Tu pouvais rester en écoute dans le thread principale avec MsgWaitForMultipleObjectsEx ? Ou alors faire du 'polling' dans OnIdle?
    MsgWaitForMultipleObjectsEx est bloquant non ? Du coup je ne pourrais plus faire de traitement dans mon thread principal.
    Je ne sais pas ce qu'est le polling.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par coincoin73 Voir le message
    MsgWaitForMultipleObjectsEx est bloquant non ? Du coup je ne pourrais plus faire de traitement dans mon thread principal.
    Il est bloquant sur les évènements et sur la réception de message. Donc, si dans ton thread principal tu ne fait rien d'autre que d'attendre des interactions IHM, cela doit pouvoir suffire. A essayer?

    Citation Envoyé par coincoin73 Voir le message
    Je ne sais pas ce qu'est le polling.
    Le polling consiste à demander régulièrement l'état plutôt qu'à se mettre en attente. L'idée dans ton cas est alors: Dans le OnIdle de ton thread principal tu fais un WaitForMultipleObjects non bloquant, et si certains sont positionnés tu fais le traitement, sinon, tu retourne. Régulièrement, OnIdle est appelé sans pour autant bloquer ton appli.

Discussions similaires

  1. Temps CPU et temps d'éxécution
    Par t_om84 dans le forum Général Python
    Réponses: 1
    Dernier message: 04/09/2005, 12h27
  2. Temps cpu
    Par chama dans le forum Administration système
    Réponses: 5
    Dernier message: 25/07/2005, 11h41
  3. Aide pour l'analyse d'un problème de gestion de temps
    Par PAINCO dans le forum Décisions SGBD
    Réponses: 8
    Dernier message: 03/06/2005, 15h49
  4. Thread et occupation CPU
    Par kramer dans le forum C++Builder
    Réponses: 11
    Dernier message: 24/05/2005, 21h57
  5. [VC++6][DX9] Problème de thread lors d'un blit ...
    Par grandjouff dans le forum DirectX
    Réponses: 2
    Dernier message: 12/06/2003, 22h22

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