Passage par référence

Résolu
neoTHGLF Messages postés 65 Date d'inscription dimanche 7 septembre 2003 Statut Membre Dernière intervention 17 décembre 2007 - 5 août 2005 à 16:28
cs_Bidou Messages postés 5486 Date d'inscription dimanche 4 août 2002 Statut Membre 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.

5 réponses

cs_Bidou Messages postés 5486 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
6 août 2005 à 18:58
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
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 août 2005 à 16:55
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 !
0
neoTHGLF Messages postés 65 Date d'inscription dimanche 7 septembre 2003 Statut Membre Dernière intervention 17 décembre 2007
5 août 2005 à 17:18
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.
0
neoTHGLF Messages postés 65 Date d'inscription dimanche 7 septembre 2003 Statut Membre Dernière intervention 17 décembre 2007
7 août 2005 à 00:20
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Bidou Messages postés 5486 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
7 août 2005 à 11:19
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
0
Rejoignez-nous