Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

affichage au fur et à mesure

9 réponses
Avatar
pierre
Bonjour,
mon problème se pose sur compact fwk 2.0 mais j'imagine que la problematique
est la meme sur winform. Concretement, j'ai développé une classe qui contient
un thread (en fait, une classe(ou plutot objet ;) qui me balance en continue
les trames MNEA de mon GPS).

ce que j'aimerai, c'est les afficher au fur et à mesure dans un label.
et là, je galère...

pour l'instant, je me balade avec le multithrading, les delegate, invoke,
etc... (et, bien sur, ca marche tjs pas-> overflow à tout les coup)

y a t'il un moyen plus simple? Suis je en train d'écraser les mouches à la
dynamite?

Je vous remercie à l'avance de vos réponses et/ou suggestions
Pierre

9 réponses

Avatar
Gilles TOURREAU
Le Tue, 24 Jul 2007 00:46:01 +0200, pierre
a écrit:

Bonjour,
mon problème se pose sur compact fwk 2.0 mais j'imagine que la
problematique
est la meme sur winform. Concretement, j'ai développé une classe qui
contient
un thread (en fait, une classe(ou plutot objet ;) qui me balance en
continue
les trames MNEA de mon GPS).

ce que j'aimerai, c'est les afficher au fur et à mesure dans un label.
et là, je galère...

pour l'instant, je me balade avec le multithrading, les delegate, invoke,
etc... (et, bien sur, ca marche tjs pas-> overflow à tout les coup)

y a t'il un moyen plus simple? Suis je en train d'écraser les mouches à
la
dynamite?

Je vous remercie à l'avance de vos réponses et/ou suggestions
Pierre





Utilises la méthode Form.Invoke().

Cela permet d'executer une méthode dans le thread qui s'occupe de
l'affichage...

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
pierre
Merci Gilles mais là, je suis completement paumé.

Ca fait maintenant des heures que je suis là dessus et je ne comprends
toujours pas. En fait, je pense que je ne comprends pas le principe. Tout les
exemples que je vois, il y a les 2 thread dans la meme classe. Mmoi, j'ai un
objet qui tourne et qui balance les trames et je veux juste voir des trames
s'afficher dans mon label

Finalement, quelqu'un connait il un tutoriel ou pourrait m'expliquer le
principe.
Merci beaucoup de votre aide
Pierre
Avatar
Gilles TOURREAU
Le Tue, 24 Jul 2007 22:30:00 +0200, pierre
a écrit:

Merci Gilles mais là, je suis completement paumé.

Ca fait maintenant des heures que je suis là dessus et je ne comprends
toujours pas. En fait, je pense que je ne comprends pas le principe.
Tout les
exemples que je vois, il y a les 2 thread dans la meme classe. Mmoi,
j'ai un
objet qui tourne et qui balance les trames et je veux juste voir des
trames
s'afficher dans mon label

Finalement, quelqu'un connait il un tutoriel ou pourrait m'expliquer le
principe.
Merci beaucoup de votre aide
Pierre



Peux-tu montrer ton code au niveau de l'appel à Control.Invoke() ?

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
Gilles TOURREAU
Le Tue, 24 Jul 2007 23:20:23 +0200, Gilles TOURREAU
a écrit:

Le Tue, 24 Jul 2007 22:30:00 +0200, pierre
a écrit:

Merci Gilles mais là, je suis completement paumé.

Ca fait maintenant des heures que je suis là dessus et je ne comprends
toujours pas. En fait, je pense que je ne comprends pas le principe.
Tout les
exemples que je vois, il y a les 2 thread dans la meme classe. Mmoi,
j'ai un
objet qui tourne et qui balance les trames et je veux juste voir des
trames
s'afficher dans mon label

Finalement, quelqu'un connait il un tutoriel ou pourrait m'expliquer le
principe.
Merci beaucoup de votre aide
Pierre



Peux-tu montrer ton code au niveau de l'appel à Control.Invoke() ?

Cordialement




Normalement tu devrais faire un truc du genre :

Dans ton objet qui tourne :

private void AfficherInfo(string info)
{
InstanceForm.libelle_a_Afficher = info;
InstanceForm.Invoke(InstanceForm.Actualiser);
}

Dans ta Form il faut déclarer une variable membre :

string libelle_a_Afficher;

et une méthode qui s'occupe d'afficher le contenu de cette variable :

//Selon la doc sous CF il faut que : "le délégué doit être une instance de
EventHandler"
//Donc il faut prendre ce prototype de cette méthode
private void Actualiser(object sender, EventArgs e)
{
this.MonLabel.Text = libelle_a_afficher;
}


****** EXPLICATIONS ******

Sous .NET tu ne peux normalement pas manipuler "tous les objets Form
(TextBox, ...etc)" dans un autre Thread que celui qui a crée la Form !
Tu es donc obligé d'appelé la méthode Invoke() dont son but est d'executer
une méthode dans le Thread de la Form...

Un exemple pour t'imaginer la situation :
Imagine 2 personnes qui marche (L'un s'appelle "Form" et l'autre "Other").
Other ne peux pas dire à "Form" tourne à droite, à gauche...etc. Cependant
Other peut laisser un bout de papier ou il écrit : "Tourne à droite" et
c'est Form après qui lit ce bout de papier et qui tourne à droite...

Grosso-modo c'est ce principe là que tu dois garder en tête....

Sous CF tu est obligé de faire une gymnastique particulière pour le
passage des paramètres (c'est pour cela qu'il faut mettre une variable
membree "libelle_a_Afficher") sous .NET classique tu peux directement
faire ceci :

private void Actualiser(string libelle)
{
this.MonLabel.Text = libelle;
}

Et appeler cette méthode via le Invoke :
InstanceForm.Invoke(InstanceForm.Actualiser, "Blablabla");

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
pierre
Merci beaucoup Gilles de toutes ces explications.
Pour le moment, je suis au taf et je ne peut donc pas bosser dessus mais je
regarde ca ce soir. Encore Merci.

Sinon, hier, j'ai essayé une nouvelle méthode (dans l'idée de contourner et
finalement, ca me parait plus rigoureux) : ma classe GPS me balance un
evenment qui contient la trame MNEA que je récupère . Je pense etre près de
la réussite (j'ai arreté de chercher vers 2H du mat;). Dans mon argsEvent,
j'ai bien ma trame mais boum, il ne veut pas l'afficher et demande un invoke
->meme problematique que le double thread.
Je vais bien lire ce soir ce que tu m'as écrit et t'envoyer mon morceau de
code.
Encore une fois, Merci beaucoup
a+
Pierre




"Gilles TOURREAU" a écrit :

Le Tue, 24 Jul 2007 23:20:23 +0200, Gilles TOURREAU
a écrit:

> Le Tue, 24 Jul 2007 22:30:00 +0200, pierre
> a écrit:
>
>> Merci Gilles mais là, je suis completement paumé.
>>
>> Ca fait maintenant des heures que je suis là dessus et je ne comprends
>> toujours pas. En fait, je pense que je ne comprends pas le principe.
>> Tout les
>> exemples que je vois, il y a les 2 thread dans la meme classe. Mmoi,
>> j'ai un
>> objet qui tourne et qui balance les trames et je veux juste voir des
>> trames
>> s'afficher dans mon label
>>
>> Finalement, quelqu'un connait il un tutoriel ou pourrait m'expliquer le
>> principe.
>> Merci beaucoup de votre aide
>> Pierre
>
> Peux-tu montrer ton code au niveau de l'appel à Control.Invoke() ?
>
> Cordialement
>

Normalement tu devrais faire un truc du genre :

Dans ton objet qui tourne :

private void AfficherInfo(string info)
{
InstanceForm.libelle_a_Afficher = info;
InstanceForm.Invoke(InstanceForm.Actualiser);
}

Dans ta Form il faut déclarer une variable membre :

string libelle_a_Afficher;

et une méthode qui s'occupe d'afficher le contenu de cette variable :

//Selon la doc sous CF il faut que : "le délégué doit être une instance de
EventHandler"
//Donc il faut prendre ce prototype de cette méthode
private void Actualiser(object sender, EventArgs e)
{
this.MonLabel.Text = libelle_a_afficher;
}


****** EXPLICATIONS ******

Sous .NET tu ne peux normalement pas manipuler "tous les objets Form
(TextBox, ...etc)" dans un autre Thread que celui qui a crée la Form !
Tu es donc obligé d'appelé la méthode Invoke() dont son but est d'executer
une méthode dans le Thread de la Form...

Un exemple pour t'imaginer la situation :
Imagine 2 personnes qui marche (L'un s'appelle "Form" et l'autre "Other").
Other ne peux pas dire à "Form" tourne à droite, à gauche...etc. Cependant
Other peut laisser un bout de papier ou il écrit : "Tourne à droite" et
c'est Form après qui lit ce bout de papier et qui tourne à droite...

Grosso-modo c'est ce principe là que tu dois garder en tête....

Sous CF tu est obligé de faire une gymnastique particulière pour le
passage des paramètres (c'est pour cela qu'il faut mettre une variable
membree "libelle_a_Afficher") sous .NET classique tu peux directement
faire ceci :

private void Actualiser(string libelle)
{
this.MonLabel.Text = libelle;
}

Et appeler cette méthode via le Invoke :
InstanceForm.Invoke(InstanceForm.Actualiser, "Blablabla");

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr



Avatar
pierre
Bonsoir Gilles,
Finalement, ce soir, je n'ai pas pu bosser autant que je le voulais. je n'ai
donc pas refait mon programme avec le double thread (il faut quand meme que
je réussise à le faire fonctionner car ca me sera utile dans ce projet ou un
autre) mais j'ai essayé de modifier la méthode avec evenment avec tes
conseils. Malheureusement, je n'ai pas réussi.voici où j'en suis:


----dans la classe qui balance les trames GPS, j'ai mis:

public delegate void NouvellePositionEventHandler(object sender,
cTrameEventArgs e);
// j'ai ajouté une classe cTrameEventArgs dans le projet.
public event NouvellePositionEventHandler NouvellePosition;

dans le constructeur de la classe

readThread = new Thread(LireMNEA);

dans la méthode LireMNEA()
...
if (strTramme.Substring(0, 6) == "$GPRMC") //Trame de position en MNEA
{
cTrameEventArgs e = new cTrameEventArgs(strTramme);
if (e != null) NouvellePosition(this, e);

}
...

---dans ma formPrincipale (déclenché sur un clic bouton)


pGPS = new cGPS(NomPort, VitesseBaud, Parité, LongueurBitMessage, BitDeStop);
pGPS.NouvellePosition += new cGPS.NouvellePositionEventHandler
(pGPS_NouvellePosition);

et la méthode:

void pGPS_NouvellePosition(object sender, cTrameEventArgs e)
{
libelle_a_Afficher = e.EventText;
lblTrame.Invoke(new
cGPS.NouvellePositionEventHandler(this.pGPS_NouvellePosition),
libelle_a_Afficher);
//this.Invoke(Actualiser, libelle_a_Afficher);

throw new Exception("The method or operation is not
implemented.");
}

et l'autre méthode:

private void Actualiser(string libelle)
{
lblTrame.Text = libelle;
}


--- ici, ca plante. j'ai essayé de tenir compte de tes indications (remis en
commentaire) mais je les applique mal. pourtant libelle_a_Afficher contient
bien la trame!
Ici, ca bloque pour le delegate: avec "new cGPS.NouvellePositionE...", ca
plate à l'execution et avec "this.Invoke(Actualiser,...", ca ne compile pas :
il veut un delegate et pas une méthode.
Une petite question: je n'ai qu'une form pour l'instant dans mon programme.
si je mets this pour l'instance de la form, ca change qq chose? (comment puis
je connaitre le nom de mon objet instantiation de la classe formPrincipal?

Encore merci de ton aide et de tes explications.
Pierre

PS: je vais essayer de faire discrétos, à midi, un projet double frame sur 2
classes pour tester au taf.
Avatar
Gilles TOURREAU
Le Thu, 26 Jul 2007 04:06:03 +0200, pierre
a écrit:

Bonsoir Gilles,
Finalement, ce soir, je n'ai pas pu bosser autant que je le voulais. je
n'ai
donc pas refait mon programme avec le double thread (il faut quand meme
que
je réussise à le faire fonctionner car ca me sera utile dans ce projet
ou un
autre) mais j'ai essayé de modifier la méthode avec evenment avec tes
conseils. Malheureusement, je n'ai pas réussi.voici où j'en suis:


----dans la classe qui balance les trames GPS, j'ai mis:

public delegate void NouvellePositionEventHandler(object sender,
cTrameEventArgs e);
// j'ai ajouté une classe cTrameEventArgs dans le projet.
public event NouvellePositionEventHandler NouvellePosition;

dans le constructeur de la classe

readThread = new Thread(LireMNEA);

dans la méthode LireMNEA()
...
if (strTramme.Substring(0, 6) == "$GPRMC") //Trame de position en MNEA
{
cTrameEventArgs e = new cTrameEventArgs(strTramme);
if (e != null) NouvellePosition(this, e);

}
...

---dans ma formPrincipale (déclenché sur un clic bouton)


pGPS = new cGPS(NomPort, VitesseBaud, Parité, LongueurBitMessage,
BitDeStop);
pGPS.NouvellePosition += new cGPS.NouvellePositionEventHandler
(pGPS_NouvellePosition);
et la méthode:

void pGPS_NouvellePosition(object sender, cTrameEventArgs e)
{
libelle_a_Afficher = e.EventText;
lblTrame.Invoke(new
cGPS.NouvellePositionEventHandler(this.pGPS_NouvellePosition),
libelle_a_Afficher);
//this.Invoke(Actualiser, libelle_a_Afficher);
throw new Exception("The method or operation is not
implemented.");
}

et l'autre méthode:

private void Actualiser(string libelle)
{
lblTrame.Text = libelle;
}


--- ici, ca plante. j'ai essayé de tenir compte de tes indications
(remis en
commentaire) mais je les applique mal. pourtant libelle_a_Afficher
contient
bien la trame!
Ici, ca bloque pour le delegate: avec "new cGPS.NouvellePositionE...", ca
plate à l'execution et avec "this.Invoke(Actualiser,...", ca ne compile
pas :
il veut un delegate et pas une méthode.
Une petite question: je n'ai qu'une form pour l'instant dans mon
programme.
si je mets this pour l'instance de la form, ca change qq chose? (comment
puis
je connaitre le nom de mon objet instantiation de la classe
formPrincipal?

Encore merci de ton aide et de tes explications.
Pierre

PS: je vais essayer de faire discrétos, à midi, un projet double frame
sur 2
classes pour tester au taf.



Est-ce que tu peux donner les détails du plantage... (Message de
l'exception).

Comme je te l'ai dis dans mon précédent post, ton délégué Actualiser doit
être forcement de type EventHandler en CF (cf la doc)...

**** Tu est donc obligé de faire ceci comme méthode :

private void Actualiser(object sender, EventArgs e)
{

}

**** Pour l'appeler cette méthode du doit faire un truc du genre :

this.Invoke(new EventHandler(Actualiser), this, e); //e étant le
paramètre de type cTrameEventArgs de ta méthode NouvellePosition


**** Et essayes ceci dans la méthode Actualiser :

private void Actualiser(object sender, EventArgs e)
{
lblTrame.Text = ((cTrameEventArgs)e).EventText;
}


**** Pourrais-tu être plus précis au niveau de ta question :
Une petite question: je n'ai qu'une form pour l'instant dans mon
programme.
si je mets this pour l'instance de la form, ca change qq chose? (comment
puis
je connaitre le nom de mon objet instantiation de la classe
formPrincipal?




Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
pierre
Bonsoir Gilles

Après quelques jours d'interruption sur mon projet, je m'y suis remis. Je
rentrais à des heures indescentes et j'avoue ne pas toujours eu envie de m'y
remettre (et l'envie est mon moteur quand je programme chez moi). Ce soir,
c'était "action" et, en suivant tes conseils (et en relisant 50 fois ce que
tu as écrit!), ca a marché(j'y croyais plus)

Enfait, pour etre honnete, je n'ai presque eu qu'à recopier ton code:

j'ai juste remplacé
this.Invoke(new EventHandler(Actualiser), this, e);
par
this.Invoke(new cGPS.NouvellePositionEventHandler(Actualiser), this, e);
(par contre, j'ai pas compris pourquoi ",this, e" marche puisque la méthode
invoke n'a que 1 ou 2 parametres et là, j'en compte 3).

En tout cas, JE TE REMERCIE BEAUCOUP
Bonne journée
Pierre



"Gilles TOURREAU" a écrit :

Le Thu, 26 Jul 2007 04:06:03 +0200, pierre
a écrit:

> Bonsoir Gilles,
> Finalement, ce soir, je n'ai pas pu bosser autant que je le voulais. je
> n'ai
> donc pas refait mon programme avec le double thread (il faut quand meme
> que
> je réussise à le faire fonctionner car ca me sera utile dans ce projet
> ou un
> autre) mais j'ai essayé de modifier la méthode avec evenment avec tes
> conseils. Malheureusement, je n'ai pas réussi.voici où j'en suis:
>
>
> ----dans la classe qui balance les trames GPS, j'ai mis:
>
> public delegate void NouvellePositionEventHandler(object sender,
> cTrameEventArgs e);
> // j'ai ajouté une classe cTrameEventArgs dans le projet.
> public event NouvellePositionEventHandler NouvellePosition;
>
> dans le constructeur de la classe
>
> readThread = new Thread(LireMNEA);
>
> dans la méthode LireMNEA()
> ...
> if (strTramme.Substring(0, 6) == "$GPRMC") //Trame de position en MNEA
> {
> cTrameEventArgs e = new cTrameEventArgs(strTramme);
> if (e != null) NouvellePosition(this, e);
>
> }
> ...
>
> ---dans ma formPrincipale (déclenché sur un clic bouton)
>
>
> pGPS = new cGPS(NomPort, VitesseBaud, Parité, LongueurBitMessage,
> BitDeStop);
> pGPS.NouvellePosition += new cGPS.NouvellePositionEventHandler
> (pGPS_NouvellePosition);
> et la méthode:
>
> void pGPS_NouvellePosition(object sender, cTrameEventArgs e)
> {
> libelle_a_Afficher = e.EventText;
> lblTrame.Invoke(new
> cGPS.NouvellePositionEventHandler(this.pGPS_NouvellePosition),
> libelle_a_Afficher);
> //this.Invoke(Actualiser, libelle_a_Afficher);
> throw new Exception("The method or operation is not
> implemented.");
> }
>
> et l'autre méthode:
>
> private void Actualiser(string libelle)
> {
> lblTrame.Text = libelle;
> }
>
>
> --- ici, ca plante. j'ai essayé de tenir compte de tes indications
> (remis en
> commentaire) mais je les applique mal. pourtant libelle_a_Afficher
> contient
> bien la trame!
> Ici, ca bloque pour le delegate: avec "new cGPS.NouvellePositionE...", ca
> plate à l'execution et avec "this.Invoke(Actualiser,...", ca ne compile
> pas :
> il veut un delegate et pas une méthode.
> Une petite question: je n'ai qu'une form pour l'instant dans mon
> programme.
> si je mets this pour l'instance de la form, ca change qq chose? (comment
> puis
> je connaitre le nom de mon objet instantiation de la classe
> formPrincipal?
>
> Encore merci de ton aide et de tes explications.
> Pierre
>
> PS: je vais essayer de faire discrétos, à midi, un projet double frame
> sur 2
> classes pour tester au taf.

Est-ce que tu peux donner les détails du plantage... (Message de
l'exception).

Comme je te l'ai dis dans mon précédent post, ton délégué Actualiser doit
être forcement de type EventHandler en CF (cf la doc)...

**** Tu est donc obligé de faire ceci comme méthode :

private void Actualiser(object sender, EventArgs e)
{

}

**** Pour l'appeler cette méthode du doit faire un truc du genre :

this.Invoke(new EventHandler(Actualiser), this, e); //e étant le
paramètre de type cTrameEventArgs de ta méthode NouvellePosition


**** Et essayes ceci dans la méthode Actualiser :

private void Actualiser(object sender, EventArgs e)
{
lblTrame.Text = ((cTrameEventArgs)e).EventText;
}


**** Pourrais-tu être plus précis au niveau de ta question :
> Une petite question: je n'ai qu'une form pour l'instant dans mon
> programme.
> si je mets this pour l'instance de la form, ca change qq chose? (comment
> puis
> je connaitre le nom de mon objet instantiation de la classe
> formPrincipal?


Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr



Avatar
Gilles TOURREAU
Le Wed, 08 Aug 2007 02:54:43 +0200, pierre
a écrit:

Bonsoir Gilles

Après quelques jours d'interruption sur mon projet, je m'y suis remis. Je
rentrais à des heures indescentes et j'avoue ne pas toujours eu envie de
m'y
remettre (et l'envie est mon moteur quand je programme chez moi). Ce
soir,
c'était "action" et, en suivant tes conseils (et en relisant 50 fois ce
que
tu as écrit!), ca a marché(j'y croyais plus)

Enfait, pour etre honnete, je n'ai presque eu qu'à recopier ton code:

j'ai juste remplacé
this.Invoke(new EventHandler(Actualiser), this, e);
par
this.Invoke(new cGPS.NouvellePositionEventHandler(Actualiser), this, e);
(par contre, j'ai pas compris pourquoi ",this, e" marche puisque la
méthode
invoke n'a que 1 ou 2 parametres et là, j'en compte 3).

En tout cas, JE TE REMERCIE BEAUCOUP
Bonne journée
Pierre




Cela fait plaisir à entendre.

Pour information, la méthode Invoke prend un premier paramètre de type
Delegate et un second qui correspond à nombre de paramètres variables (0,
1, 2, 10, 100).
Regardes du coté du mot-clé "params" en C#...

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr