Passage par référence [Résolu]

Messages postés
65
Date d'inscription
dimanche 7 septembre 2003
Dernière intervention
17 décembre 2007
- - Dernière réponse : cs_Bidou
Messages postés
5507
Date d'inscription
dimanche 4 août 2002
Dernière intervention
20 juin 2013
- 7 août 2005 à 11:19
Bonjour,

je travaille actuellement sur une programme à la con afin de m'initier au C#. Venant du C++, l'adaptation n'est pas trop dure.

Mon problème est le suivant :

Je dispose de deux classes :



using System.Windows.Forms;
using System.Threading;


public class calcul_pos_x //Sert à caculer la position de la souris sur l'axe x de l'écran
{
private double total;
private Label affichage_texte;

public calcul_pos_x(ref double tot,ref Label label) //Constructeur
{
total = tot;
affichage_texte = label;
}
}

public class calcul_pos_y //Sert à caculer la position de la souris sur l'axe y de l'écran
{
private double total;
private Label affichage_texte;

public calcul_pos_y(ref double tot,ref Label label) //Constructeur
{
total = tot;
affichage_texte = label;
}
}


Donc le constructeur de chacune de ces deux classe prends comme parametres deux références.

Ces deux classes intègrent de plus, chacune une méthode. On obtient donc :



using System.Windows.Forms;
using System.Threading;


public class calcul_pos_x //Sert à caculer la position de la souris sur l'axe x de l'écran
{
private double total;
private Label affichage_texte;

public calcul_pos_x(ref double tot,ref Label label) //Constructeur
{
total = tot;
affichage_texte = label;
}

public void calculate()
{
while(true)
{
System.Threading.Thread.Sleep(1);
mouse_pos_x = MousePosition.X; /* Obtient la position actuelle de la souris sur l'axe x */
if (mouse_pos_x != tmp_x)
{
double sub;
sub = (Math.Abs(mouse_pos_x - tmp_x)) / 96; /* Calcul la distance parcourue par la souris sur l'écran en pouces */
total += sub * 2.54; /* Convertit la distance en Centimetre et l'ajoute à total */
affichage_texte.Text = total.ToString();
affichage_texte.Refresh();
}
tmp_x = mouse_pos_x;
}
}

}

public class calcul_pos_y //Sert à caculer la position de la souris sur l'axe y de l'écran
{
private double total;
private Label affichage_texte;

public calcul_pos_y(ref double tot,ref Label label) //Constructeur
{
total = tot;
affichage_texte = label;
}

public void calculate()
{

while(true)
{
System.Threading.Thread.Sleep(1);
mouse_pos_x = MousePosition.Y; /* Obtient la position actuelle de la souris sur l'axe y */
if (mouse_pos_y != tmp_y)
{
double sub;
sub = (Math.Abs(mouse_pos_y - tmp_y)) / 96; /* Calcul la distance parcourue par la souris sur l'écran en pouces */
total += sub * 2.54; /* Convertit la distance en Centimetre et l'ajoute à total */
affichage_texte.Text = total.ToString();
affichage_texte.Refresh();
}
tmp_y = mouse_pos_y;
}
}
}


La méthode Calculate() intégrée aux deux classes sert à calculer en
centimètres la distance que la souris à parcourue sur l'écran.

Lorsque le cacul est terminé, le résultat est stocké dans un double, celui qui a été passé par référence au constructeur lors de la création de l'objet dans une Form que voici :



public Form1()
{
double distance_parcourue;
Label label1 = new Label();

calcul_pos_x calculator_x = new calcul_pos_x(ref distance_parcourue,ref label1);
calcul_pos_y calculator_y = new calcul_pos_y(ref distance_parcourue,ref label1);

Thread x_thread = new Thread(new ThreadStart(calculator_x.calculate));
Thread y_thread = new Thread(new ThreadStart(calculator_y.calculate));

x_thread.Start();
y_thread.Start();

}


Donc, lorsque la Form1 est chargée, deux thread sont créés, un pour calculer la distance sur x et l'autre la distance sur y.

Normalement durant l'éxécution des deux thread, la variable double distance_parcourue devrait augmenter.

Lorsque je déplace la souris sur l'axe X de l'écran, distance_parcourue augmente bel et bien.

De même, lorsque je déplace la souris sur l'axe Y.



Alors quel est le probleme ? vous demandez-vous.

Le probleme c'est que par exemple si je me déplace sur l'axe X de 20 centimètres, alors distance_parcourue est égal à 20, si je continue sur le même axe à me déplacer de 5 centimètres, alors, distance_parcourue égal 25.

Maintenant, je décide de me déplacer de 10 centimètres sur l'axe Y, et bien là, au lieu d'être égal à 35, distance_parcourue égal 10.

En revanche si je décide de ma redéplacer sur l'axe X de 5 centimètres(par exemple), alors distance_parcourue est égal à 30, ce qui est tout à fait logique.

Maintenant je me redéplace de 40 sur l'axe Y, et bien distance_parcourue égal 50.

Ainsi, au lieu d'additionner la distance parcourue sur les deux axes,
le programme semble additionner d'un coté la distance parcourue par la
souris sur l'axe Y, et de l'autre coté, la distance parcourue sur l'axe
Y, comme s'il existait 2 variables... je ne comprends pas d'où ça
vient. Enfin, je suis presque sûr que ça vient du passage par
référence, mais je ne comprends pas pourquoi.



Quelqu'un aurait - il une suggestion ? (s'il vous plait je vous en
suplis, ça va faire plus de 4 heures que je suis sur ce probleme, plus
une heure de rédaction de ce post) ;).

Cordialement.
Afficher la suite 

Votre réponse

5 réponses

Meilleure réponse
Messages postés
5507
Date d'inscription
dimanche 4 août 2002
Dernière intervention
20 juin 2013
3
Merci
Salut,
Ton problème est le suivant : tu veux résoudre quelque chose d'extrêmement simple en faisant compliqué. Pourquoi créer pleins de classes, de méthodes, de passages par références, passer des Labels d'un coin à un autre, ect. ?


J'ai très très rapidement écrit un code qui fonctionne. Je n'ai construit aucune classe, ce qui n'est pas forcément la meilleure approche, à toi de l'adapter (je te propose de créer une class qui intégre le code si dessous, et de faire une méthode ou Property qui get la valeur total du chemin effectué par la souris depuis que le programme est démarré (évidemment, quand on parle de chemin total, on parle de la distance de l'abscisse aditionnée à celle de l'ordonnée, ce qui n'est pas vraiment la distance totale... mais faisons simple pour commencer) :


private int tot = 0;
private int xLast = 0;
private int yLast = 0;

public void Cal()
{
while (true)
{
int x = Control.MousePosition.X;
int y = Control.MousePosition.Y;
tot += Math.Abs(x-xLast) + Math.Abs(y-yLast);
xLast = x;
yLast = y;
// Ici à faire : Mise à jour du Label de manière asynchrone pour éviter le cross-threading
System.Threading.Thread.Sleep(10);
}
}

Bien entendu, cette méthode doit être démarrée dans un nouveau Thread.
Exemple :


System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(this.Cal));
t.Start();


Voilà c'est tout...

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Bidou
Messages postés
3248
Date d'inscription
lundi 25 avril 2005
Dernière intervention
27 octobre 2012
0
Merci
Salut,

1 ) pourquoi passer le label par ref, c'est déja un type référence !?
2 ) http://www.csharp.fr/tutorial.aspx?ID=174 ( Cross-threading )
3 ) Concurrence des thread peut être ? opérateur lock !
Commenter la réponse de Lutinore
Messages postés
65
Date d'inscription
dimanche 7 septembre 2003
Dernière intervention
17 décembre 2007
0
Merci
Bonjour,



1) si je ne passe pas le label par référence, je ne peux pas y accèder
à partir de la méthode Calculate(), peut-être que je fais une erreur
quelque part.

2) j'ai lu mais j'ai du mal à comprendre en quoi ça résoud mon problème

3) Je suis débutant, je t'avouerais que ça fait un peu trop longtemps
maintenant que je galère, pour avoir le courage d'essayer de comprendre
de vagues explications



est ce que tu pourrais être plus clair ?

Cordialement.
Commenter la réponse de neoTHGLF
Messages postés
65
Date d'inscription
dimanche 7 septembre 2003
Dernière intervention
17 décembre 2007
0
Merci
Merci beaucoup pour cette réponse, j'ai entre temps trouvé une solution à mon probleme en utilisant justement des variables globales. Seulement à la base je préférais éviter les variable globales. Un lointain souvenir me dit qu'il est plutôt déconseillé de les utiliser. J'avais aussi créé deux threads parce que les calculs étaient lourd et que le programme freezait.
La solution que j'ai mise au point est exactement celle que vous venez de me conseiller, à une différence près ; j'ai un thread qui calcul la distance sur x et un autre qui calcule la distance sur y.

Merci à tous les deux pour vos réponses.
Cordialement.
Commenter la réponse de neoTHGLF
Messages postés
5507
Date d'inscription
dimanche 4 août 2002
Dernière intervention
20 juin 2013
0
Merci
Ca dépend de ce qu'on entend par "variables globales". En C# les variables globales à une application n'existent pas réellement. En loccurance, les variables

private int tot = 0;
private int xLast = 0;
private int yLast = 0;

que j'ai déclaré sont des variables de classes qui sont de plus privées, ce qui ne posent aucun problème de sécurité... On peut donc les utiliser sans aucun soucis.
Sinon à propos des Threads, ça me paraît un peu inutile d'en créer deux étant donné la faible charge de travail que demande les instructions tournant en boucle dans le while... mais bon, c'est un peu un détail !

[Pub] http://www.csharpfr.com/auteurdetail.aspx?ID=13319 [\Pub]
C# forever
Commenter la réponse de cs_Bidou

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.