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 Forms Discussion :

[c#]threads : ou est la limite d'execution du thread ?


Sujet :

Windows Forms

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2003
    Messages
    837
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Février 2003
    Messages : 837
    Points : 377
    Points
    377
    Par défaut [c#]threads : ou est la limite d'execution du thread ?
    Bonjour à tous,

    Difficile d'ennoncer une question claire vis à vis de mon probleme... c'est plutot compliqué.
    Voilà ce qui me pose tant probleme :
    Dans mon soft, j'ai une classe dont une méthode créé un thread pour lancer un process (commande dos) qui génere un traitement long (encodage).
    Une fois cet encodage terminé, la classe doit envoyer un evenement disant qu'il est terminé.
    Jusque là, mes evenements ont toujours fonctionné mais avec l'utilisation d'un thread ça se complique.
    Donc voila grosso modo comment ca se passe :

    J'ai une méthode void Toutencoder() qui lance mes threads (ça gere une liste d'attente donc les lance un par un).
    Dans cette methode, on lance un nouveau thread faisant appel à la méthode LancerCommande. Dans lancerCommande() j'ai les opérations devant se faire donc en parallele (contenues dans le thread). Dans cette méthode, j'execute ce que je dois faire, puis je fais appel à un delegate pour lancer mon évenement une fois que mon process est terminé (en fait dans LancerCommande, je lance mon process, je fais un waitForExit pour attendre la fin de l'encodage puis j'invoke la methode lançant l'evenement).
    Cette methode que j'invoke pour lancer l'evenement est toute bete, des plus classiques, si mon evenement!=null alors tu m'en créé un nouveau et tu l'envoies.

    Sauf que maintenant, quand je met ce que doit faire mon programme lors de la reception de cet evenement, il me dit que ça n'a pas été lancé par le meme thread que celui qui gere -notamment- la progressbar que je souhaite modifier.

    J'ai donc l'impression que tout ce qui suit l'evenement est toujours contenu dans mon thread créé. Je ne sais pas vraiment comment ca se passe...

    Voici un petit bout de code pour vous expliquer un peu mieux :

    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
     
    MethodeEncoder()
    {
    ...
    thread tr = new Thread(this.lancerEncodage);
    tr.start();
    ...
    }
     
    LancerEncodage()
    {
    process myproc = new process();
    ...
    myproc.start();
    myproc.waitForExit();
    FinEncodageDelegate FE = new FinEncodageDelegate(FinEncodage);
    FE.Invoke();
    }
     
    FinEncodage()
    {
    if(EncodeEnded!=null)
    EncodeEnded(this,EncodeEndedEventArgs());
    }
     
    Et dans mon code au niveau de l'ihm :
     
    void MaClasse_EncodeEnded(object sender, EncodeEndedEventArgs e)
    {
    progressbar1.value = 20;
    }
    Si quelqu'un a une idée, je suis preneur !
    Merci d'avance
    @ ++

  2. #2
    Nouveau membre du Club
    Inscrit en
    Novembre 2006
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 22
    Points : 26
    Points
    26
    Par défaut
    Salut,

    En effet tu ne peux pas appeller un evenement à partir d'un thread sans certaines précautions.


    Essaye la méthode suivante:
    progressbar1.invoke(EncodeEnded,new object[2] {this,EncodeEndedEventArgs});


    ça devrais le faire.

  3. #3
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Bonjour,

    tu pourrais utiliser le traitement asynchrone avec un delegate, ou tu pourrais utiliser les évenements avec AutoResetEvent et ManualResetEvent, ce qui me semble approprier dans ton cas.

    Par contre, il y a un webcast sur les threads sur le site de Microsoft, tu pourrais aller y faire un tour. Il est en Vb.net mais même si tu ne connais pas, il y a des notions très interessante à comprendre.

    Le Multi-Threading avec Visual Basic 2005

    Avec tout ça, si tu ne t'en sors pas...

    Bye.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2003
    Messages
    837
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Février 2003
    Messages : 837
    Points : 377
    Points
    377
    Par défaut
    Salut,

    dfgs83 : l'utilisation de Progressbar1 dans ma classe n'est pas bonne... logique vu que c'est une classe, je sépare le coté metier du coté presentation. Maintenant, ce que je ne comprend pas vraiment c'est que logiquement le thread que je créé ne devrait comporter QUE les instructions figurant dans la méthode lancerEncodage().
    Or, quand je lance mon evenement, ca doit etre à la fin du thread, donc soit je lance l'evenement dans la méthode lancerEncodage soit je passe par autre chose (que je ne connais pas).
    Donc en utilisant la premiere solution, j'ai cru comprendre par mes recherches sur le net qu'il fallait utiliser un invoke afin d'appeler à partir du thread créé une methode en l'executant dans le thread principal.
    Donc pour tenter le coup, voici ce que j'ai fait :

    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
    Maclasse
    {
     
    private delegate void FinEncodageDelegate
    private FinEncodageDelegate FE;
     
    //methode qui lance mon thread d'encodage
    MethodeEncoder()
    {
    ...
    thread tr = new Thread(this.lancerEncodage);
    tr.start();
    ...
    }
     
    //methode qui execute mon traitement lourd dans le thread créé
    a la fin, on doit envoyer un evenement dans le thread principal de la form et non dans le thread créé.
    LancerEncodage()
    {
    process myproc = new process();
    ...
    myproc.start();
    myproc.waitForExit();
    FinEncodageDelegate FE = new FinEncodageDelegate(FinEncodage);
    FE.Invoke();
    }
     
    //methode appelée par le invoke qui va lancer l'evenement à l'ihm
    FinEncodage()
    {
    if(EncodeEnded!=null)
    EncodeEnded(this,EncodeEndedEventArgs());
    }
    }
     
    Et dans mon code au niveau de l'ihm :
     
    void MaClasse_EncodeEnded(object sender, EncodeEndedEventArgs e)
    {
    progressbar1.value = 20;
    }
    Bah là ca me lance un cross threaded Exception.
    Donc je ne vois pas trop là...

    Pilloutou : Merci pour le webcast malheureusement, je ne peux pas telecharger au taf... et le soir je n'ai pas le temps
    Pour le delegate, Cf au dessus, ce que je viens d'expliquer (c'est ce que tu voulais dire ?)
    Sinon pour autoresetevent et manualresetevent je vais voir la doc, merci

    @ bientot

  5. #5
    Nouveau membre du Club
    Inscrit en
    Novembre 2006
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 22
    Points : 26
    Points
    26
    Par défaut
    Salut, je crois que j'ai compris ton besoin. C'est logique de vouloir séparer l'interface de la classe qui peut être distribuée et utilisée par d'autres personnes.

    Une fois sur le net j'ai trouvé cette technique:

    #region Raise event thread safe
    {
    MessageReportEventHandler handler=ClientDisconnected;//<- mon event d'ex

    MessageReportEventArgs e2 = new MessageReportEventArgs("Client disconnected");
    if (handler != null)
    {
    foreach (MessageReportEventHandler singleCast in handler.GetInvocationList())
    {
    ISynchronizeInvoke syncInvoke = singleCast.Target as ISynchronizeInvoke;

    if ((syncInvoke != null) && (syncInvoke.InvokeRequired)) syncInvoke.Invoke(singleCast, new object[] { this, e2 });
    else singleCast(this, e2);
    }
    }
    }
    #endregion

    Bon sang il faut vraiment que j'aprenne à inserrer du code proprement sur ce forum......

Discussions similaires

  1. [WinDev] Est-il possible d'executer une application Win32 dans un site ?
    Par ran_hery dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 22/09/2006, 15h41
  2. [Ecran TFT]Est-on limité à la résolution indiquée
    Par NicolasJolet dans le forum Périphériques
    Réponses: 6
    Dernier message: 06/09/2006, 21h25
  3. [VB6]Le nombre de contrôle d'une IHM est-il limité?
    Par lio33 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 07/02/2006, 12h20
  4. Réponses: 14
    Dernier message: 07/12/2005, 16h56
  5. Réponses: 6
    Dernier message: 27/10/2005, 13h58

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