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 :

[MFC] multithread, communication père<->fils


Sujet :

MFC

  1. #1
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut [MFC] multithread, communication père<->fils
    Bonjour,
    J'ai une application qui fonctionne actuellement en monothread et j'aimerai la passer en multithread. Mon application permet d'analyser un lot d'images. L'interface que j'ai conçu sous visual permet à l'utilisateur de choisir le nombre de thread qu'il souhaite lancer (chaque thread effectuant plusieurs traitement sur une image). j'aimerai initialement lancer le nombre de thread precisé par l'utilisateur simultanement sur des images differentes. Ensuite, dès qu'un thread à terminé de traiter son image, j'aimerai le quitter pour ensuite le lancer (ou en lancer un nouveau) sur l'image qui suit.
    Voila pour le principe (j'espere que vous avez compris).
    Plusieurs problèmes se posent :
    • - Tout d'abord, seul le père à la liste des images à traiter, il doit donc communiquer à chaque thread qu'il execute, l'image qu'il doit traiter.
      - Ensuite, le thread doit faire un resumer des resultats qu'il a obtenu pour le transmettre au père.

      Faut-il commencer par faire quelque chose comme ça? :
      for (int i=0; i<nb_thread_a_lancer; i++)
      {
      AfxBeginThread( processOneImage, this);
      }
      sachant que "processOneImage" est une fonction qui traite une image.
      Merci pour votre aide et vos conseils.

  2. #2
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    Une autre question :
    Est ce qu'une la fonction qui est appelé par le thread peut récuperer l'ID du thread qui l'execute?

  3. #3
    mat.M
    Invité(e)
    Par défaut
    Oui il faut passer "this" qui référence le processus parent et dans la fonction processOneImage , traiter "this" en faisant des "casts" éventuellement ( transtypage )


  4. #4
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 266
    Points : 6 688
    Points
    6 688
    Billets dans le blog
    2
    Par défaut Re: [MFC] multithread, communication père<->fils
    Citation Envoyé par Joeleclems
    chaque thread effectuant plusieurs traitement sur une image
    tu veux dire que plusieurs threads vont modifer simultanément le même fichier??!

    Citation Envoyé par Joeleclems
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i=0; i<nb_thread_a_lancer; i++)
    {
        AfxBeginThread( processOneImage, this);
    }
    Il me semble que AfxBeginThread retourne d'Id du thread. Tu peux donc créer un tableau (m_aThreadIds dans le code ci-dessous) dans lequel tu enregistre les Ids de tes threads (ça peut être pratique pour garder un contrôle sur eux, pour les arêter par exemple):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i=0; i<nb_thread_a_lancer; i++)
    {
        m_aThreadIds[i] = AfxBeginThread( processOneImage, this);
    }
    hope it helps

  5. #5
    Membre éprouvé Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 52

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Points : 1 122
    Points
    1 122
    Par défaut Re: [MFC] multithread, communication père<->fils
    Bonjour,
    Citation Envoyé par Joeleclems
    Bonjour,
    ... L'interface que j'ai conçu sous visual permet à l'utilisateur de choisir le nombre de thread qu'il souhaite lancer (chaque thread effectuant plusieurs traitement sur une image). j'aimerai initialement lancer le nombre de thread precisé par l'utilisateur simultanement sur des images differentes.
    Donc, ici tu as besoin d'un thread par images à traiter, attention cependant, sur Windows le nombre de thread par processus n'est pas illimité non plus !

    Citation Envoyé par Joeleclems
    Ensuite, dès qu'un thread à terminé de traiter son image, j'aimerai le quitter pour ensuite le lancer (ou en lancer un nouveau) sur l'image qui suit.
    Il n'est pas besoin de le quitter mais de le suspendre !
    Première solution: Dans la boucle de traitement du thread, tu émets un evènement lorsque le thread a terminé son image, puis il se suspend. L'application "chapeau" recevant cet évènement, lui envoit un évènement de réveil avec comme paramètre un handle sur le nouveau fichier image à traiter.
    En gros, c'est l'application "chapeau" qui ouvre le fichier image.

    Autre solution, comme j'en ai l'habitude, je dirais plus facile, car elle ne dépend pas de la MessagePump, utiliser une zone de mémoire partagée dans laquelle l'application chapeau place les noms de fichiers à traiter comme une fifo.
    Le thread lorsuq'il commence un traitement va lire l'emplacement qui lui est réservé, ouvre l'image et la traite. Une fois le traitement intégralement terminé, il met à null, ou à une valeur identifié comme "Worked" la chaîne de traitement dans la fifo. Il se suspend.
    L'application place alors un nouveau nom de fichier à traiter à cet emplacement, puis elle réveille le thread.
    Citation Envoyé par Joeleclems
    - Tout d'abord, seul le père à la liste des images à traiter, il doit donc communiquer à chaque thread qu'il execute, l'image qu'il doit traiter.
    - Ensuite, le thread doit faire un resumer des resultats qu'il a obtenu pour le transmettre au père.
    Une zone partégée me parait trés appropriée à ton problème.
    Regarde l'aide de CreateFileMapping, CreateViewOfFile ...

    Citation Envoyé par Joeleclems
    Faut-il commencer par faire quelque chose comme ça? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (int i=0; i<nb_thread_a_lancer; i++)
    {
        AfxBeginThread( processOneImage, this);
    }
    Oui, uniquement si tu utilises une classe de thread MFC comme CThread.

    Attention cependant, l'application principale doit garantir de ne pas donner une même image à deux thread.

  6. #6
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    merci pour vos conseils, je vais essayer de faire quelque chose.

  7. #7
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    Une fois le traitement intégralement terminé, il met à null, ou à une valeur identifié comme "Worked" la chaîne de traitement dans la fifo. Il se suspend.
    L'application place alors un nouveau nom de fichier à traiter à cet emplacement, puis elle réveille le thread.
    Comment faire pour "suspendre" un thread et pour ensuite le "reveiller"?

  8. #8
    Membre éprouvé Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 52

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Points : 1 122
    Points
    1 122
    Par défaut
    Tu utilises la méthode suspend pour l'endormir.

    Dans l'application principale, tu utilises Resume.

    Regardes dans la FAQ à la rubrique sur les threads Malheureusement il n'y a pas tout, mais au moins tu as un début.

  9. #9
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    ok merci

  10. #10
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    Je n'est plus aucun affichage depuis que j'essaye de faire du multi thread... voila ce que je fais :
    (toutes les variables avec "_" devant sont des variables de classes)

    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
     
    //Lancement des threads
    for(int i=0; i<nb_thread; i++)
    {	
    	if(nb_image > 0 )
    	{
    		nb_image--;
    		ThreadParam thread_param;
    		//On met à jour l'image à traiter
    		imageFile = FindFile::combinePath(find.filelist[0].path, string(sortNamesCSTRING[p_nb_total_of_files - nb_image]));
    		_avnct_bas->SetWindowText(imageFile.c_str());
    		thread_param._has_finish = false;
    		thread_param._image_file = imageFile;
    		thread_param._sensibilite = sensibilite;
    		_data.push_back(thread_param);
    		_threads.push_back(AfxBeginThread(processOneImage, this));
    		_corres.push_back(_threads[i]->m_nThreadID);
    		}
    	}
    	_avnct_haut->SetWindowText("Traitement des images");
    	//Relancement des threads en boucle tant que le nombre d'image total n'a pas déja été traité
    	while(nb_image>0)
    	{
    		for (int i=0; i<nb_thread; i++)
    		{
    		//Si le thread a terminé de traiter son image
    			if(_data[i]._has_finish)
    			{
    			//On décremente le nombre d'images restantes
    			p_staying_files--;
    			sprintf(staying_files,"%d",p_nb_total_of_files - p_staying_files);
    			_processed_img.SetWindowText(staying_files);
    			_progress_bar_gnl->SetPos( (p_nb_total_of_files - p_staying_files) * 100 / p_nb_total_of_files );
    			_progress_bar->SetPos( (p_nb_total_of_files - nb_image +1) * 100 / nb_image );
    		//On enregistre le resultat dans le rapport
    		_data[i]._bad_image._folders = dossier_source;
    		_report._vreport.push_back(_data[i]._bad_image);		_report.saveLigne();
     
    		//On met à jour l'image à traiter
    		imageFile = FindFile::combinePath(find.filelist[0].path, string(sortNamesCSTRING[p_nb_total_of_files - nb_image]));
    		_data[i]._image_file = imageFile;
    		_data[i]._sensibilite = sensibilite;
     
    		//On reveille le thread
    		ResumeThread(_threads[i]->m_hThread);
    		_data[i]._has_finish = false;
    			}
    		}
    	}
    	//On attend la fin d'execution de tous les threads
    	int cpt = 0;
    	_finish = true;
    	for (unsigned int i=0; i<_threads.size(); i++)
    	{
    		WaitForSingleObject(_threads[i]->m_hThread, INFINITE);
    	}
    Au secours!

  11. #11
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    J'ai aussi une interrogation : Est-il possible que le processus père ne réagisse que lorsqu'un de ses processus fils se termine? si oui comment?
    Autrement dit : comment faire pour rendre la main à l'utilisateur? à l'interface graphique?

  12. #12
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    J'ai beau essayer de modifier la priorité des threads, ça ne change rien... je pense que le problème vient de la boucle qui attend que les processus fils aient terminés... mais je ne sais pas comment faire autrement!

  13. #13
    Membre habitué
    Inscrit en
    Avril 2004
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 122
    Points : 138
    Points
    138
    Par défaut
    Bonjour.

    Bien sur, ta boucle d'attente bloque ton parent.
    Si ton parent est une fenêtre, pourquoi n'envoies-tu pas un message à ta fenêtre quand un thread se termine, cela débloquerai ton parent et ton interface.

    Autrement, si ton parent n'est pas une fenêtre, je pense que tu devrais créer un thread parent dans lequel tu metrrais le code que tu as écrit ci-dessus.

  14. #14
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    Le parent est une boite de dlg.
    Il faut utiliser la fonction : WaitForSingleObject( un_handle, "INFINITE") pour "bloquer" le parent?
    En fait j'ai modifié mon code est quand mon thread se termine il fait une mise à jour d'evenement (avecd SetEvent). Si je comprends bien, je dois recuperer cette eveenement par la fonction WaitForSingleObject. Comment fonctionne cette fonction? est-ce qu'elle bloque le processus père?

  15. #15
    Membre habitué
    Inscrit en
    Avril 2004
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 122
    Points : 138
    Points
    138
    Par défaut
    Il faut savoir qu'un Event à deux etats, signalé et non signalé.

    Quand tu fait SetEvent, tu bascule l'event en état signalé.

    La fonction waitforsingleobject permet d'attendre qu'un Event soit signalé.
    Mais cette fonction va bloquer ta fenêtre.

    ton parent étant un fenêtre, tu pourrais faire en sorte que quand un thread se termine il envoie un message à ta fenêtre (comme ca tu n'as pas a attendre qu'il se termine) en passant son id comme parametre du message.

    Ca pourrais resoudre ton probleme je pense.

  16. #16
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    J'aimerai bien, mais comment faire pour envoyer un message? autrement que par event? ne vaudrait-il pas mieux que je lance un thread pour l'affichage?

  17. #17
    Membre habitué
    Inscrit en
    Avril 2004
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 122
    Points : 138
    Points
    138
    Par défaut
    vu que le parent est une fenêtre, à la fin d'un thread du peut faire un postmessage sur le Hwnd de ton parent.

    L'autre solution est aussi valable.

  18. #18
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    et comment fonctionne postmessage?Quand le thread se termine il fait un postmessage sur le Hwnd de mon parent : et comment celui-ci le recupere t-il dans le parent?

  19. #19
    Membre habitué
    Inscrit en
    Avril 2004
    Messages
    122
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 122
    Points : 138
    Points
    138
    Par défaut
    Postmessage permet d'envoyer un message à une fenêtre.

    Regarde l'aide dans le MSDN, tout est expliqué.


    Tu dois te définir un message comme suit :

    #define WM_FIN_THREAD WM_USER+100

    Ton message doit être défini par une valeur supérieur à WM_USER.

    Dans la message map de ta fenêtre tu ajoute

    ON_MESSAGE(WM_FIN_THREAD,OnFinThread)


    dans ton .h de ta fenêtre tu ajoutes le prototype de ta fonction dans la close AFX_MSG (si tu ne l'a pas, met la dans la section protected)

    afx_msg void OnFinThread(WPARAM wparam,LPARAM lparam);

    Tu implémentes ensuite cette fonction dans ton cpp

    void Fenetre::OnFinThread(WPARAM wparam,LPARAM lparam)
    {
    //id du thread dans le wparam
    DWORD dw_ThreadID = (DWORD)wparam;

    //traitement

    }

    A la fin du thread tu fais ça

    :ostMessage(TonParent->GetSafeHwnd,WM_FIN_THREAD,id du thread,0);


    et voila.


    En espérant que ça t'aide.

  20. #20
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 111
    Points : 53
    Points
    53
    Par défaut
    merci beaucoup

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Communication père/fils tableau d'entiers.
    Par boblinux dans le forum Débuter
    Réponses: 13
    Dernier message: 26/11/2014, 16h09
  2. Gtk et communication père fils
    Par troumad dans le forum GTK+ avec C & C++
    Réponses: 9
    Dernier message: 22/04/2011, 22h04
  3. Mauvaise communication père/fils signaux
    Par Shargat dans le forum Débuter
    Réponses: 4
    Dernier message: 14/03/2010, 12h14
  4. [MFC]MultiThreads
    Par _matt_44 dans le forum MFC
    Réponses: 4
    Dernier message: 10/05/2006, 11h48
  5. Réponses: 4
    Dernier message: 23/05/2004, 17h14

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