Threads taches lourdes

Juliane15 Messages postés 3 Date d'inscription jeudi 21 mai 2009 Statut Membre Dernière intervention 23 mai 2009 - 20 mai 2009 à 22:53
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 - 24 mai 2009 à 19:51
Salut tout le monde



Je développe une application (détecter les routes et dessiner leurs bordures sur l'image.) en c# qui exécute des fonctions lourdes se trouvant toutes dans une seule classe et qui font appel les unes aux autres.



J'ai besoin de rajouter une fonction qui consiste à arrêter l'exécution à un moment donné pour se contenter du résultat préliminaire, ceci doit être fait avec les threads et la méthode invoke.



A présent je ne parviens pas à ce résultat, en appuyant sur la forme en plein exécution celle-ci devient bloquante, merci de me donner une idée comment le faire.



Voici le schéma approximatif :



private

void ButtonExecute_Click(object sender, EventArgs e)<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>





{





Thread
t = newThread(newThreadStart(launchInvoke));





t.Start();








}





private

void launchInvoke()





{





pictureBox1.Invoke(newmyDelegate (myclasse.myMethode), this);





}





private

delegate
void
myDelegate(baseForm bForm);








private

void ButtonStop_Click(object sender, EventArgs e)





{





Stop = true;





}





myclasse
.myMethode se charge de trouver les points des bordures et de les mettre dans un ArrayList soit arrayListPoints, puis dans l'évènement :





private

void pictureBox1_Paint(object sender, PaintEventArgs e)





{





// dessiner les bordures en se servant de arrayListPoints





}

3 réponses

cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
22 mai 2009 à 20:27
Bonsoir,

Il n'y a pas beaucoup de solutions,
Soit tu Kill violament le thread
Soit tu positionnes un booleen dans un ojbet global (singleton static) que tu testes dans toutes tes boucles pour savoir si tu continues ou pas.

C# is amazing, enjoy it!
0
Juliane15 Messages postés 3 Date d'inscription jeudi 21 mai 2009 Statut Membre Dernière intervention 23 mai 2009
23 mai 2009 à 16:39
Je parviens à résoudre le problème du parallélisme en utilisant backgroundWorker, par contre, il reste le problème du dessin des bordures, parce que dans myclasse.myMethode je fais bForm.pictureBox1.Refresh(); ce qui me signale une erreur « accès à un contrôle par un thread autre que celui qui l’a crée », j’ai du ensuite désactiver la génération de cette exception par Control.CheckForIllegalCrossThreadCalls = false; (ce qui n’est pas recommandé), de ce fait, j’ai obtenu une exécution (normale) mais sans que les bordures ne soient dessinées sur l’image (pictureBox1_Paint n’est jamais appelée).

J’ai pensé également de faire (sur la classemyClass) :

private delegate void delegateRefresh (object sender, PaintEventArgs e);

private static void pictureBox1Refresh()
{
   bForm.pictureBox1.Refresh();   // bForm : mon formulaire de base
}
private static void myMethode (baseForm bForm)
{
  // extraction c.à.d. calcule des points des bordures et les mettre dans
  // arrayListPoints

  bForm.pictureBox1.Invoke(newdelegateRefresh(bForm.pictureBox1_Paint), [param]);
}

Je ne sais pas si cette solution pourrai être juste, mais ma difficulté actuelle réside sur le passage des paramètres [param] (la création d’un object et d’un PaintEventArgs) merci de m’aider à continuer cette solution ou de me proposer une autre.
0
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
24 mai 2009 à 19:51
Bonjour,

Pour régler le probleme de l'exception d'acces au ressource depuis un autre thread tu dois fournir un delegate, mais pas necessairement avec la même signature que l'evenement.

ex pour inserrer un message dans un texte box
Dans ta form définit un delegate simple:
        delegate void SetData(string data);

au moment ou tu veux ecrire dans le text box, ajout ce code:

               if (textBox2.InvokeRequired)
                {
                    textBox2.Invoke(new SetData(AddMessage), new object[] { "mon message" });
                }
                else
                {
                     AddMessage ("mon message");
                }

puis définis la methode AddMessage
void AddMessage(string message)
        {
            textBox2.Text += Environment.NewLine + message;
            textBox2.Select(textBox2.Text.Length, 1);
            textBox2.ScrollToCaret();
        }

En fait le delegate permet l'appel à une methode depuis un autre thread, l'execution de la methode est deleguée à l'objet invoké.

La signature du delegate correspond à celle de la methode qui sera appelée, dans ce cas:
delegate voidSetData(string data);
void AddMessage(string message)

L'instanciation du delegate set à associer la mehode qui sera appelée:
new SetData(AddMessage)

Mais pour l'execution il faut passer à la methode les parametres qu'elle attend, dans notre cas un seul parametre de type string.
textBox2.Invoke(new SetData(AddMessage), new object[] { "mon message" });

La methode Invoke etant generique il faut pouvoir passer n'inporte quel type d'objets et comme le nombre peut varié, la seul solution est un tableau d'objet.
Les parametres doivent être passé dans l'odre de leur déclaration.

ex, si la méthode avait attendu 2 parametres: 
   void AddMessage(string message, bool scroll)

Le delegate aurrait été :
   delegate voidSetData(string data, bool scroll);

L'appel aurait été :
   textBox2.Invoke(new SetData(AddMessage), new object[] { "mon message" , true});

bon voilà, j'espere avoir été compréhensible :-)

C# is amazing, enjoy it!
0
Rejoignez-nous