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 d'affichage dans une fenetre CDialog: DoModal!


Sujet :

MFC

  1. #21
    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
    je ne comprends pas ton problème.
    quel est l'architecture du programme ? MDI /SDI / Dialog .
    à partir de la fenêtre maitre tu lances une dialogue non modale générique (pourquoi générique?) ?
    tu as un thread de travail , qui est lancé par qui ?
    le thread met à jour la dialogue non modale ?
    c'est bien ça?

  2. #22
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Architecture du programme : Dialog!

    A partir de la fenetre mère je lance une application qui se connecte à une base de données. Une fois la connexion établie on demande à l'utilisateur si il souhaite visualiser les traces en temps réel. Dans l'affirmatif je lance ma 2ème fenêtre(quipause problème).

    Ensuite les traitement sur la base commencent et on voit les traces s'afficher dans ma fenetre(+ précisement dans son Cedit). Cette 2ème fenetre est non modale pour que le programme puisse continuer à s'éxecuter après son instanciation et appeler la méthode qui écrit les traces.

    L'affichage se passe très bien!Mais quand tu click sur cette 2ème fenêtre (peut importe où, sur un de ces boutons, sur le CEdit....) alors que, au meme temps, le programme effectue des manip sur la base de données, y'a plus de reconstruction possible: cette fenetre n'as pas le temps de traiter les messages!!

    Ce que je voulais faire pour permettre le traitement de ces messages (afin que ma fenetre ne "s'étouffe" pas) est créer un thread de travail qui appelle en boucle la méthode PumpMessage() pour "donner de l'air" à cette fenetre.
    Je suis certain que le thread que je crée appele bel et bien PumpMessages() mais
    le problème persiste: on dirait que l'appel de PumpMessages ne permet pas le traitement des messages correspondants aux clicks sur la zone client de la fenetre.

    Voila j'espère que je me suis fait comprendre!

    Merci d'avoir accordé autant d'attention à mon pb!

  3. #23
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Voilà ça fait un moment que je galère maintenant, j'arrive pas à résoudre mon bug
    je vous passe mon code vous pouvez le télécharger à cette adresse:
    http://www.megaupload.com/?d=4RRCS0JE
    En fait, j'ai fait un code qui reproduit exactement mon bug. Lisez les commentaires du fichier Traitements.h pour bien assimuler la nature de mon bug!

    Donc ,j'ai une CDialog CAffichageTraces contenant un bouton "Lancer". Quand on clique sur ce dernier, on appelle une fonction fctPrincipale() qui va lancer des traitements: en réalité ce sont des traitements sur une base de données mais pour faire simple, je les ai remplacés par des ::Sleep() sinon y'aura trop de code inutil pour la compréhension de mon bug.

    FctPrincipale() instancie la classe CfenetreLog, l'instance est dlg, elle est non modale, qui est en fait déclarée en tant que variable globale (déclarée dans Traitements.cpp)
    Une fois instanciée, la fenetre s'affiche et au fur et à mesure que le programme s'exécute on y écrit des traces.
    Lors de l'affichage(donc quand les traitements sont en cours) si vous touchez à cette fenetre dlg, elle plante, plus de reconstruction possible, on dirait qu'elle ne trouve pas le temps de "respirer" (=de traiter les messages)

    Compilez ce code et exécutez le et vous allez mieux assimiler mon problème.

    Comment résoudre ce bug??
    Si vous avez des questions n'hésitez pas!

    Merci pour votre aide!

    NB: mes dialog sont crées dynamiquement sans ressources!

  4. #24
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    attention chaque thread a sa propre pompe a message !!!

    appeler PumpMessage() dans un thread pour faire "respirer" un autre thread est impossible ...

    T'es pas forcément obligé de faire un autre thread, tout depend bien sur de comment est géré ton traitement sur les bases de données.

    Moi je ferais un seul et unique thread, et le traitement sur les BDD se fera dans CWinApp::OnIdle(). --> remplacer CWinApp par la classe dérivée du projet.

    OnIdle() est appelé lorsque la pompe a message est vide, de là tu peux faire un traitement spécifique, mais attention il faut rendre la main régulierement sinon l'appli sera figée. --> Il faut donc "sequencer" le travail a faire par petit paquet pas trop long en terme de temps d'execution.

    c'est la methode la plus simple

    @+

  5. #25
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Sinon il y a la methode inverse:

    au lieu que ça soit les MFC qui appelle ton traitement des BDD, tu peux faire que ton traitement appelle les MFC, notamment la fonction PumpMessage() a l'interieur de ta boucle.

    Mais tout ça est a condition que tu puisses "sequencer" le traitement.

    Sinon, faut faire un WorkerThread, qui fait que du traitement BDD mais ne créé surtout pas d'interface GUI. --> mettre en place une comm entre le thread exclusivement GUI et le thread exclusivement BDD.

    @+

  6. #26
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par stephdim Voir le message
    attention chaque thread a sa propre pompe a message !!!

    appeler PumpMessage() dans un thread pour faire "respirer" un autre thread est impossible ...
    Ok, c'est noté!

    Citation Envoyé par stephdim Voir le message
    Moi je ferais un seul et unique thread, et le traitement sur les BDD se fera dans CWinApp::OnIdle(). --> remplacer CWinApp par la classe dérivée du projet.

    OnIdle() est appelé lorsque la pompe a message est vide, de là tu peux faire un traitement spécifique, mais attention il faut rendre la main régulierement sinon l'appli sera figée. --> Il faut donc "sequencer" le travail a faire par petit paquet pas trop long en terme de temps d'execution.

    c'est la methode la plus simple
    Justement le traitement par paquet n'est pas possible car ça dépend de la taille des tables Oracle manipulées: parfois ça ne prends meme pas un milliseconde et parfois ça prend une minute voir plus. Et bien évidement, je ne peux pas suspendre le traitement d'une table pour "rendre la main"
    Donc à mon avis cette méthode ne peut pas etre une solution.

    Mais j'ai une question: OnIdle() est appellée quand la pompe des messages est vide. Supponsons que OnIdle() lance une traitement et au moment que le traitement est en cours un message arrive à la pompe qui sera plus vide. Que se passera-t-il? La pompe va attendre la fin de OnIdle()?? ou bien va prendre la main "par force"??

  7. #27
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Mais j'ai une question: OnIdle() est appellée quand la pompe des messages est vide. Supponsons que OnIdle() lance une traitement et au moment que le traitement est en cours un message arrive à la pompe qui sera plus vide. Que se passera-t-il? La pompe va attendre la fin de OnIdle()?? ou bien va prendre la main "par force"??
    Tout est confiné dans le meme thread, c'est justement le role de la pompe à message de "sérialiser" les évènements.

    En gros, la boucle des MFC c'est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for (;;)
    {
      PumpMessage();             // on traite les messages en attente de la pile FIFO
      OnIdle();                       // traitement quand la pile est vide
    }
    Il est clair que si OnIdle() prend 10 sec, l'appli sera figée pendant ce temps là, et ne reagira pas aux évènements, ni a l'affichage des fenetres .....


    @+

  8. #28
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par stephdim Voir le message
    Sinon il y a la methode inverse:

    au lieu que ça soit les MFC qui appelle ton traitement des BDD, tu peux faire que ton traitement appelle les MFC, notamment la fonction PumpMessage() a l'interieur de ta boucle.

    Mais tout ça est a condition que tu puisses "sequencer" le traitement.
    Justement ce n'est pas possible de "séquencer" le traitement
    Donc pas trop le choix, faut utiliser un WorkerThread!
    Citation Envoyé par stephdim Voir le message
    Sinon, faut faire un WorkerThread, qui fait que du traitement BDD mais ne créé surtout pas d'interface GUI. --> mettre en place une comm entre le thread exclusivement GUI et le thread exclusivement BDD.

    @+
    Comment mettre en place une comm? Est ce par l'envoi d'un message privé?
    Est ce le thread de traitement BDD, qui d'ailleurs doit disposer d'un handle de ma fenetre, doit faire un SendMessage() pour écrire les traces dans cette fenetre?
    Merci
    @+

  9. #29
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Oui tu peux te servir de SendMessage() d'un thread vers un autre. Mais attention, il y a des cas particuliers qui provoquent des deadlock

    tu peux faire ça:

    m_pEdit->SetWindowText(...)

    sans prob depuis un autre thread

    @+

  10. #30
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 396
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 396
    Points : 20 507
    Points
    20 507
    Par défaut
    Citation Envoyé par vonemya Voir le message
    Le dialogue n'est pas créé dans le thread!

    Le dialogue c'est une variable globale (créée par new)donc meme les méthodes de la classe CWorkerThread ont accès à cette instance, ce qui est équivalent à ce que tu me dis de faire. Mais ça plante!
    Bien lire ce que a écrit Farscape ; la CDialog ne doit pas être crée dans un Thread.
    Si cela plante c'est comme tu l'écris un problème d'accès concurrent.
    void CMafenetre::OnBouton()
    {
    AfxBeginThread(TheThread,GetSafeHwnd(),THREAD_PRIORITY_NORMAL) ;
    }
    Il est souhaitable d'utiliser des CEvent plutot pour synchroniser correctement.
    Tu vas créer un CEvent qui va tourner en tache de fond et au besoin lui donner la notification de démarrer avec CEvent::SetEvent()

    Citation Envoyé par stephdim Voir le message
    Mais attention, il y a des cas particuliers qui provoquent des deadlock
    @+
    Problème de partage de variable qui peut se résoudre avec des sections critiques et CCriticalSection
    Une section critique c'est basiquement un méchanisme qui verrouille l'accès à une variable donnée déclarée dans un processus fils

  11. #31
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par Mat.M Voir le message
    Il est souhaitable d'utiliser des CEvent plutot pour synchroniser correctement.
    Tu vas créer un CEvent qui va tourner en tache de fond et au besoin lui donner la notification de démarrer avec CEvent::SetEvent()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CMafenetre::OnBouton()
    {
    AfxBeginThread(TheThread,GetSafeHwnd(),THREAD_PRIORITY_NORMAL) ;
    }
    Mais, si je ne me trompe pas, OnBouton(), ne sera appelée que si le message correspondant au click sur le bouton soit traité!!! Ce message est mis en attente parce qu'à ce stade (avant que OnBouton() soit appelée) il n'ya qu'un seul thread qui en train de faire des traitements BDD, donc pas le temps de traiter ce message --> OnBouton n'est pas appelée et par conséquent le thread n'est pas crée!!

    Si tu as le temps, est ce que tu peux regarder le code que j'ai mis en ligne à cette adresse:
    http://www.megaupload.com/?d=4RRCS0JE
    Je simule mon bug

  12. #32
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Je viens de jetter un oeil a ton source et je trouve que tu te compliques vachement la vie !!

    J'ai pas vu de thread dans ton source ; mais en gros voila ce qu'il faut faire:

    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
     
    void  CAffichageTracesDlg::OnLancerApplication()
    {
      CFenetreLog *pDlg=new CFenetreLog(....);    // on créé la fenetre
     
       ...           // on affiche la fenetre ....
     
      AfxBeginThread(fctPrincipale,pDlg);   // on créé un thread et on passe en paramètre le pointeur de la fenetre "Log"
     
      // c'est tout
    }
     
    UINT __cdecl fctPrincipale(LPVOID pParam)     // la procédure du thread
    {
      CFenetreLog *pDlg=(CFenetreLog*)pParam;   // on récupère le pointeur de la fenetre "Log"
     
      .....   // on fait du taff
     
      pDlg->afficherTrace("un joli message");
     
      .....   // et ainsi de suite
     
      return 0;                        // le thread est fini
    }
    Tu conserves tel quel ta fonction afficherTrace (c'est parce que les fonctions utilisées par afficherTrace renvoies vers des SendMessage() (wrapper de CEdit) que ça marche )

    Ca devrait fonctionner sans probleme.

    Pourquoi faire des dialogues dynamiques ?!? je trouve que ça fait un peu usine à gaz pour juste faire ça ... enfin bon c'est hors sujet ça

    @+

  13. #33
    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
    Citation Envoyé par farscape Voir le message
    la dialogue ne doit pas être crée dans le thread
    si l'appel se fait à partir d'une interface (dialogue par exemple).
    tu créés ta dialogue non modal par un new ,tu stocks le pointeur dans l'interface en tant que donnée membre.
    Au moment de l'AfxBeginThread tu fournis un pointeur de l'interface au thread.
    dans le thread tu as donc accès a l'interface et au pointeur sur la dialogue non modale.
    c'est exactement ce que j'avais conseillé de faire ..

  14. #34
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Merci farscape et stephdim ça marche bien.

    Mais j'ai une 2ème application très semblable à celle que j'ai décrite. Il y a une seule petite différence qui apparemment fait en sorte qu'on arrive pas à écrire dans la fenetre.

    Dans cette 2ème application, la méthode d'ecriture dans le fenetre afficherTrace() est appelée indirectement dans la fonction fctPrincipale() exécutée par le second thread crée. Je m'explique:

    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
    
    
    void fonction1()
    {
       ....
       // on appelle la fonction afficherTrace(message);
       .....  
    }
    
    
    void fonction2()
    {
       ....
       // on appelle la fonction afficherTrace(message);
       .....  
    }
    
    
    void fonction3()
    {
       ....
       // on appelle la fonction afficherTrace(message);
       .....  
    }
    
       .....
       .....
    
    
     UINT __cdecl fctPrincipale(LPVOID pParam)     // la procédure du thread
    {
      //pDlg est déclaré local à la fctPrincipale()
      CFenetreLog *pDlg=(CFenetreLog*)pParam;   // on récupère le pointeur de la fenetre "Log"
     
      .....   // on fait du taff
     
      fonction1;
      fonction2;
      fonction3;
      .......
      .......
      .....   // et ainsi de suite
     
      return 0;                        // le thread est fini
    }
    Donc vous voyez bien que la portée du pointeur pDlg ne doit pas se limiter à la fonction fctPrincipale()!!
    Comme il y a plein de fonctions appelés dans fctPrincipale() et qui appellent de leur tour afficherTrace(comme fonction1,fonction2...) je ne peux pas passer pDlg en parametre, ça demande des énormes modif dans le code.
    Quand ej dis plein c'est un fichier de 25743 lignes exactement c'est pas moi qui l'ai fait.

    Donc j'ai essayé de declarer pDlg en tant que variable globale et dans la fonction fctPrincipale() je lui affecte le pointeur passé en parametre à cette dernière. Mais rien en s'affiche dans la fenetre Avec des fprintf je suis sûr que les traitements sur la BDD tournent bien dérrière et la fenetre qui reste sans message(la fonction afficherTrace échoue) ne plante pas!

    Une idée pour remedier à cela??

    Thanks!

  15. #35
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    ben ça ne devrait pas poser de probleme.

    Si ça marche avec une, ça marche avec plus de fonctions.

    Tu mets le pointeur de CFenetreDlg dans une var globale avant de créer le thread (pas la peine de le passer en param a la fonction du thread, si la var est globale)

    Un truc: ne pas oublier de faire un delete, sinon tu auras un memory leak

    @+

  16. #36
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par stephdim Voir le message
    ben ça ne devrait pas poser de probleme.

    Si ça marche avec une, ça marche avec plus de fonctions.

    Tu mets le pointeur de CFenetreDlg dans une var globale avant de créer le thread (pas la peine de le passer en param a la fonction du thread, si la var est globale)

    Un truc: ne pas oublier de faire un delete, sinon tu auras un memory leak

    @+
    J'ai fais comme tu m'as dit: j'instancie ma fenetre et le pointeur que je récupère je l'affecte à un pointeur global pDlg et puis , une fois le thread est crée afficherTrace() est appelé à partir de ce pointeur(pDlg->afficherTrace()) mais ça marche po le fonction afficherTrace() n'est meme pas appelé(un MessageBox à l'interieur le prouve)

  17. #37
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 159
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par vonemya Voir le message
    J'ai fais comme tu m'as dit: j'instancie ma fenetre et le pointeur que je récupère je l'affecte à un pointeur global pDlg et puis , une fois le thread est crée afficherTrace() est appelé à partir de ce pointeur(pDlg->afficherTrace()) mais ça marche po le fonction afficherTrace() n'est meme pas appelé(un MessageBox à l'interieur le prouve)

    Je me rattrappe; ça marche nickel! Je suis encore en train d'effectuer des tests, pour l'instant tous les tests reussissent. Je vais tester encore et encore.

    Merci beaucoup pour votre aide précieuse.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 7
    Dernier message: 14/02/2014, 09h00
  2. Affichage dans une fenetre
    Par mamadou_76 dans le forum Hibernate
    Réponses: 2
    Dernier message: 31/05/2007, 12h11
  3. [MySQL] problème d'affichage dans une liste
    Par bromlecornu dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 23/05/2007, 16h08
  4. Affichage dans une Fenetre edit
    Par Fred2209 dans le forum C++Builder
    Réponses: 6
    Dernier message: 20/11/2006, 10h39
  5. Problème d'affichage dans une zone de "dessin"
    Par jason69 dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 28/08/2006, 16h12

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