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 :

Affichage en temps réel du résultat d'un thread


Sujet :

MFC

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut Affichage en temps réel du résultat d'un thread
    Bonjour,

    je rencontre un problème pour afficher en temps réel les résultats de procédures de traitement réalisées dans des threads.

    J'ai une classe CThreads dans laquelle sont définis 4 threads: 2 threads s'occupent de la lecture tandis que les 2 autres s'occupent du traitement des données lues. Dans les 2 threads de traitement, il y a une fonction PostMessage qui devrait appeler une fonction réalisant l'affichage en temps réel du résultat du traitement dans la fenêtre principale de l'application.

    Voici un archétype de la classe CThreads:

    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
     
     
    DWORD WINAPI CThreads::Lecture_Data0(LPVOID pvParam)
    {
    	CThreads  *pThisLD0=reinterpret_cast< CThreads *>( pvParam);
     
    	DWORD dwEvt=0;
    	DWORD dwBytesWritten=0;
    	DWORD dwBytesRead=0;
     
       if(WaitForSingleObject(pThisLD0->hEventLD0[0],INFINITE)==WAIT_OBJECT_0 && WaitForSingleObject(pThisLD0->hEventLD0[1],INFINITE)==WAIT_OBJECT_0);
     
        // LECTURE
     
        SetEvent(pThisLD0->hEventLD1[1]);
        SetEvent(pThisLD0->hEventTD0);
     
        return 0;
    }
     
    DWORD WINAPI CThreads::Lecture_Data1(LPVOID pvParam)
    {
    	CThreads  *pThisLD1=reinterpret_cast< CThreads *>( pvParam);
     
    	DWORD dwEvt=0;
    	DWORD dwBytesWritten=0;
    	DWORD dwBytesRead=0;
     
    	if(!WaitForSingleObject(pThisLD1->hEventLD1[0],INFINITE) && !WaitForSingleObject(pThisLD1->hEventLD1[1],INFINITE));
     
    	// LECTURE
     
    	SetEvent(pThisLD1->hEventLD0[1]);
    	SetEvent(pThisLD1->hEventTD1);
     
    	return 0;
    }
     
    DWORD WINAPI CThreads::Traitement_Data0(LPVOID pvParam)
    {
    	CThreads  *pThisTD0=reinterpret_cast< CThreads *>( pvParam);
    	pThisTD0->SetCurrentThreadName("Traitement Data0");
     
    	// TRAITEMENT
     
            ::PostMessage(pThisTD0->fenetre,WM_FINCALCUL,0,0);
     
    	SetEvent(pThisTD0->hEventLD0[0]);
    	SetEvent(pThisTD0->hEventFin0);
     
    	return 0;
    } 
     
    DWORD WINAPI CThreads::Traitement_Data1(LPVOID pvParam)
    {
    	CThreads  *pThisTD1=reinterpret_cast< CThreads *>( pvParam);
    	pThisTD1->SetCurrentThreadName("Traitement Data1");
     
    	//TRAITEMENT 
     
    	::PostMessage(pThisTD1->fenetre,WM_FINCALCUL,0,0);
     
    	SetEvent(pThisTD1->hEventLD1[0]);
    	SetEvent(pThisTD1->hEventFin1);
     
    	return 0;
    }
    La 2ème classe est une boite de dialogue:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    protected:
    	HICON m_hIcon;
     
    	// Generated message map functions
    	//{{AFX_MSG(CTempsReelDlg)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnStart();
    	//}}AFX_MSG
     
    	void OnReceiveFinCalcul(WPARAM wparam, LPARAM lparam); //Message privé
     
    	DECLARE_MESSAGE_MAP()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    BEGIN_MESSAGE_MAP(CTempsReelDlg, CDialog)
    	//{{AFX_MSG_MAP(CTempsReelDlg)
    	ON_BN_CLICKED(IDC_Start, OnStart)
    	ON_MESSAGE(WM_FINCALCUL,OnReceiveFinCalcul)  // message privé 
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CTempsReelDlg::OnReceiveFinCalcul(WPARAM wparam, LPARAM lparam)
    {
         // AFFICHAGE
    }

    Le problème que je rencontre est qu'au lieu que le résultat s'affiche chaque fois qu'un thread de traitement est terminé, seul le dernier résultat s'affiche au niveau de la boite de dialogue et ce lorsque tous les threads sont finis.

    Il y a visiblement quelquechose qui m'échappe. Quelqu'un aurait-il une idée?




    Merci d'avance.

    P.S. je développe sous Embedded Visual C++

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    ton pb veut dire que l'application ne recoit pas les messages windows pour se raffraichir correctement.
    ou tes thread sont un peu trop agressifs (prennent trop de cpu).
    tu as un boucle ou quelque chose qui y ressemble dans ta fonction d'affichage ?
    essaye de rajouter l'appel a un pompe a message dans ta fonction d'affichage voir faq:
    http://c.developpez.com/faq/vc/?page...rk#PumpMessage


  3. #3
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    bonsoir,

    J'ai essayé de placer la fonction PumpMessages dans la fonction OnReceiveFinCalcul mais cela ne résoud pas le problème.


    tu as un boucle ou quelque chose qui y ressemble dans ta fonction d'affichage ?
    Non pas de boucle dans la fonction d'affichage. Chaque fois que cette fonction est appelée, elle doit afficher un indicateur (ex: une moyenne) du signal acquis pendant une durée correspondant à la durée de fonctionnement d'un des deux threads de lecture.

    Par contre, il y a une boucle for dans chacun des threads de lecture et de traitement.

    Exemple:
    on considère que chaque thread de lecture lit pendant une seconde. Si on lit pendant 5 secondes, il faudra que le thread de lecture 0 effectue 3 itérations tandis que le thread de lecture 1 n'en effectuera que 2.

    J'espère que mes explications ne vous embrouilleront pas trop; j'essaierai de faire tourner les threads "à vide" demain au boulot afin de s'assurer qu'ils ne consomment pas trop.

    Merci

  4. #4
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Bonjour,

    J'ai modifié le programme pour le tester avec Visual C++ 6 et je rencontre le même problème.
    Ca n'a donc pas l'air d'être un problème de surconsommation CPU des threads vu que je retrouve le même comportement sur PC et sur PDA.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void CTempsReelDlg::OnReceiveFinCalcul(WPARAM wparam, LPARAM lparam)
    {
         AfxMessageBox(_T("essai"));
         //AFFICHAGE
    }
    Cependant, en affichant un popup chaque fois que la fonction OnReceiveFinCalcul est appelée, je vois qu'elle se lance un certain nombre de fois mais les popup apparaissent tous lorsque tous les threads sont terminés (fin de l'application) .

    On dirait que la boucle de messages est mise en sommeil durant le fonctionnement des threads et ne recoit les messages que lorsque ceux-ci sont terminés.

    Quelqu'un a-t-il déjà rencontré ce problème?




    Merci d'avance

  5. #5
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    l'affichage d'un afxmessagebox dans ta fonction n'est pas vraiment une bonne idée...
    tu n'as pas un autre controle pour surveiller l'affichage ?
    genre une list box ou tu inserais les evenements (c'est un exemple).

  6. #6
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    J'ai essayé avec une ListBox :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    void CTempsReelDlg::OnReceiveFinCalcul(WPARAM wparam, LPARAM lparam)
    {
        m_cListe.AddString(_T("essai"));
         //AFFICHAGE
    }
    j'ai 4 occurences "essai" qui apparaissent en même temps à la fin de l'application ...

  7. #7
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Je crois avoir trouvé la source du problème:

    En effet, lorsque j'effectue un PostMessage à l'intérieur de la classe de dialogue tout fonctionne correctement pour peu qu'il y ait un appel à PumpMessages après l'appel à PostMessage.

    Le problème dans mon cas vient du fait que je réalise un PostMessage à partir d'une autre classe. d'où la question qui découle de ce constat:

    comment intercepter un message envoyé à partir d'une autre classe?

  8. #8
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    passe le handle de fenetre en argument dans ton postmessage ...

  9. #9
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Ca je l'avais déjà fait mais le problème est d'activer la fonction PumpMessages de la classe Dlg à partir de la classe de lecture et de traitement.

    On dirait que la fonction PumpMessages doit être lancée au niveau de la classe de réception du message pour que cela fonctionne ...

  10. #10
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    effectivement je placerai le pump message dans le message de reception.

  11. #11
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Comme je n'arrive pas à lancer la fonction PumpMessages (avec s ) j'ai lancé la fonction PumpMessage de CWinApp mais cela a pour effet de bloquer le programme

    Voici le code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class CThreads  
    {
    public:
    CWinApp *essai;
    ...
    }
    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
     
    DWORD WINAPI CThreads::Traitement_Data0(LPVOID pvParam)
    {
       CThreads  *pThisTD0=reinterpret_cast< CThreads *>( pvParam);
       pThisTD0->SetCurrentThreadName("Traitement Data0");
     
       // TRAITEMENT
     
       ::PostMessage(pThisTD0->fenetre,WM_FINCALCUL,0,0);
       pThisTD0->essai->PumpMessage();
     
       SetEvent(pThisTD0->hEventLD0[0]);
       SetEvent(pThisTD0->hEventFin0);
     
       return 0;
    }
    Quelle est la différence entre PumpMessage de CWinApp et la fonction PumpMessages de la F.A.Q?

    J'ai aussi essayé de redéfinir une fonction PumpMessages au niveau de la classe Cthreads mais un appel à cette fonction apres le PostMessage ne résoud pas le problème.

  12. #12
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    surtout pas de pompe message dans le thread ..
    quel est le probleme pour l'appeler dans la reception du message ?

  13. #13
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Je dois avoir mal compris, je pensais que c'était là qu'il fallait que je l'appelle ...
    Il faudrait que j'appelle la fonction PumpMessages dans la fonction OnReceiveFinCalcul?
    c'est à dire :
    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
     
    void CTempsReelDlg::OnReceiveFinCalcul(WPARAM wparam, LPARAM lparam)
    {
    	PumpMessages();
    	m_cListe.AddString(_T("essai"));
    	if(i%2==0)
    	{
    		m_cVex.SetWindowText(_T("Pair"));
    		m_cVey.SetWindowText(_T("Pair"));
    		m_cVez.SetWindowText(_T("Pair"));
    	}
    	else
    	{
    		m_cVex.SetWindowText(_T("Impair"));
    		m_cVey.SetWindowText(_T("Impair"));
    		m_cVez.SetWindowText(_T("Impair"));
    	}
    	i++;
     
    }

  14. #14
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    oui et a la fin de tes setwindowtext .

  15. #15
    Membre à l'essai
    Inscrit en
    Février 2005
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 21
    Points : 15
    Points
    15
    Par défaut
    Ca ne fonctionne pas

    Le problème c'est que les messages WM_FINCALCUL sont reçus lorsque les threads de lecture et de calcul sont terminés.

    C'est pour cette raison que j'avais pensé faire un appel à la fonction PumpMessages immédiatement après le PostMessage mais je ne sais pas comment my prendre pour appeler la fonction PumpMessages définie au niveau de la classe Dlg dans les threads définis dans la classe CThreads.

Discussions similaires

  1. Affichage en temps réel des données
    Par oumokhtar dans le forum Shell et commandes GNU
    Réponses: 7
    Dernier message: 25/03/2008, 12h47
  2. Affichage en temps réel
    Par Luciefer dans le forum Interfaces Graphiques
    Réponses: 20
    Dernier message: 17/08/2007, 14h29
  3. Affichage en temps réel ??
    Par haffouff dans le forum Langage
    Réponses: 2
    Dernier message: 11/05/2006, 21h57
  4. Affichage en temps réel...
    Par beral dans le forum C++Builder
    Réponses: 6
    Dernier message: 09/02/2006, 12h05
  5. [WD9] Affichage en temps réel
    Par oz80 dans le forum WinDev
    Réponses: 4
    Dernier message: 11/01/2006, 14h06

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