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

Gestion de la memoire (Multithread).

8 réponses
Avatar
Alexandre Czysz
Bonjour

J'ai fais un petit test avec ce programme.
c'est un simple form avec un control label et un timer.
A chaque "tick" du timer la propriété Text du label est modifier.
Mon problem est que la mémoire utilisé par cette application ne cesse
d'augmenter (Task Manager).
Comment puis-je libérer la mémoire ou au moins laisser le garbage
collector s'en occuper?
Je suppose que j'aurai le même problème avec une application multithread!

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label label1;
private System.ComponentModel.IContainer components;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();

this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

this.label1.Location = new System.Drawing.Point(56, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 40);
this.label1.TabIndex = 0;
this.label1.Text = "label1";

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void timer1_Tick(object sender, System.EventArgs e)
{
LabelSetTextDelegate del = new
LabelSetTextDelegate(this.LabelSetText);
object[] paramList = new object[] {
DateTime.Now.ToLongTimeString() };
this.Invoke(del, paramList);
}

private delegate void LabelSetTextDelegate(string value);

private void LabelSetText(string value)
{
this.label1.Text = value;
}
}

8 réponses

Avatar
Remi THOMAS
"Alexandre Czysz" wrote in message
news:45215ad4$0$2231$
Bonjour

J'ai fais un petit test avec ce programme.
c'est un simple form avec un control label et un timer.
A chaque "tick" du timer la propriété Text du label est modifier.
Mon problem est que la mémoire utilisé par cette application ne cesse
d'augmenter (Task Manager).
Comment puis-je libérer la mémoire ou au moins laisser le garbage
collector s'en occuper?
Je suppose que j'aurai le même problème avec une application multithread!

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label label1;
private System.ComponentModel.IContainer components;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();

this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

this.label1.Location = new System.Drawing.Point(56, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 40);
this.label1.TabIndex = 0;
this.label1.Text = "label1";

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void timer1_Tick(object sender, System.EventArgs e)
{
LabelSetTextDelegate del = new
LabelSetTextDelegate(this.LabelSetText);
object[] paramList = new object[] {
DateTime.Now.ToLongTimeString() };
this.Invoke(del, paramList);
}

private delegate void LabelSetTextDelegate(string value);

private void LabelSetText(string value)
{
this.label1.Text = value;
}
}



Bonjour,
Déjà tu peux invoquer directement label1.Text pour y mettre la valeur.
Ensuite je pense que le garbage collector fonctionne correctement, il faut
lui laisser le temps de fonctionner.
Pour voir si tu n'as pas de fuite mémoire utilises GC.Collect() pour forcer
le compactage de la mémoire.
GC.Collect() ne dois pas être utilisé dans une application, il est
préférable de laisser la CLR gérer cela toute seul.

Rémi
Avatar
Alexandre Czysz
Chère Remi THOMAS

Merci pour votre aide.

J'ai implementé un bouton depuis lequel j'appel la fonction Collect du
Garbage Collector. Mais rien n'y fait!
l'application démarre avec 16.232Ko mais monte très vite a 16.900Ko.
l'appel de Collect ne change rien bien au contraire j'ai l'impression
que cela rajoute de la mémoire.

Alexandre Czysz

Remi THOMAS wrote:
"Alexandre Czysz" wrote in message
news:45215ad4$0$2231$
Bonjour

J'ai fais un petit test avec ce programme.
c'est un simple form avec un control label et un timer.
A chaque "tick" du timer la propriété Text du label est modifier.
Mon problem est que la mémoire utilisé par cette application ne cesse
d'augmenter (Task Manager).
Comment puis-je libérer la mémoire ou au moins laisser le garbage
collector s'en occuper?
Je suppose que j'aurai le même problème avec une application multithread!

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label label1;
private System.ComponentModel.IContainer components;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();

this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

this.label1.Location = new System.Drawing.Point(56, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 40);
this.label1.TabIndex = 0;
this.label1.Text = "label1";

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void timer1_Tick(object sender, System.EventArgs e)
{
LabelSetTextDelegate del = new
LabelSetTextDelegate(this.LabelSetText);
object[] paramList = new object[] {
DateTime.Now.ToLongTimeString() };
this.Invoke(del, paramList);
}

private delegate void LabelSetTextDelegate(string value);

private void LabelSetText(string value)
{
this.label1.Text = value;
}
}



Bonjour,
Déjà tu peux invoquer directement label1.Text pour y mettre la valeur.
Ensuite je pense que le garbage collector fonctionne correctement, il
faut lui laisser le temps de fonctionner.
Pour voir si tu n'as pas de fuite mémoire utilises GC.Collect() pour
forcer le compactage de la mémoire.
GC.Collect() ne dois pas être utilisé dans une application, il est
préférable de laisser la CLR gérer cela toute seul.

Rémi


Avatar
Michael Moreno
> GC.Collect() ne dois pas être utilisé dans une application, il est préférable
de laisser la CLR gérer cela toute seul.



ouais ben le garbage collector c'est le bordel en pratique. Je ne
compte plus les heures passees a changer les algos pour eviter que la
memoire ne soit totalement bouffee rapidement.

--
Michael
----
http://michael.moreno.free.fr/
http://port.cogolin.free.fr/
Avatar
PeeF
Bonjour.

"Alexandre Czysz" a écrit dans le message de news:
45215ad4$0$2231$
Bonjour



...
private void timer1_Tick(object sender, System.EventArgs e)
{
LabelSetTextDelegate del = new
LabelSetTextDelegate(this.LabelSetText);
object[] paramList = new object[] {
DateTime.Now.ToLongTimeString() };
this.Invoke(del, paramList);
}

private delegate void LabelSetTextDelegate(string value);

private void LabelSetText(string value)
{
this.label1.Text = value;
}
}



Comme te le dit Remi Thomas, place directement la ligne
label1.TextÚteTime.Now.ToLongTimeString()
dans ton "private void timer1_Tick" : ça simplifie beaucoup l'écriture.
Microsoft déconseille d'écrire dans les contrôles d'une Form depuis un autre
Thread et donc, en général, c'est la bonne habitude à prendre, mais là tout
est dans le même Thread.

D'autre part, dans ce que tu as écrit, la variable "del" est la même tout le
temps, crée la une seule fois en dehors de "private void timer1_Tick". Comme
tu la crées à chaque clic, ça bouffe de la mémoire.
Pareil pour l'objet paramètre "paramList". Une méthode pour ne pas avoir à
le créer à chaque fois est de prendre une variable globale créée une fois
pour toute, comme pour "del".

Bien sûr, tout celà ne règle pas le problème du GC un peu lent... Note tout
de même que, dans la partie construite par ton IDE, la fonction
InitializeComponents prend la peine de créer tous les contrôles (qui sont
des "objects"), et de les supprimer aussi à la fin par "Dispose()". Il
faudrait trouver un moyen de virer "paramList" après utilisation.
Avatar
Delf
PeeF a écrit :

Comme te le dit Remi Thomas, place directement la ligne
label1.TextÚteTime.Now.ToLongTimeString()
dans ton "private void timer1_Tick" : ça simplifie beaucoup l'écriture.
Microsoft déconseille d'écrire dans les contrôles d'une Form depuis un autre
Thread et donc, en général, c'est la bonne habitude à prendre, mais là tout
est dans le même Thread.



Une question en passant.

J'ai une form avec un label. Au chargement de la form, un thread est
lancé et doit changer la propriété Text du label. Pour celà, j'utilise
une délégate, j'ai bon ?

Merci.

--
Delf
Avatar
Alexandre Czysz
PeeF wrote:
Bonjour.

"Alexandre Czysz" a écrit dans le message de news:
45215ad4$0$2231$
Bonjour



...
private void timer1_Tick(object sender, System.EventArgs e)
{
LabelSetTextDelegate del = new
LabelSetTextDelegate(this.LabelSetText);
object[] paramList = new object[] {
DateTime.Now.ToLongTimeString() };
this.Invoke(del, paramList);
}

private delegate void LabelSetTextDelegate(string value);

private void LabelSetText(string value)
{
this.label1.Text = value;
}
}



Comme te le dit Remi Thomas, place directement la ligne
label1.TextÚteTime.Now.ToLongTimeString()
dans ton "private void timer1_Tick" : ça simplifie beaucoup l'écriture.
Microsoft déconseille d'écrire dans les contrôles d'une Form depuis un autre
Thread et donc, en général, c'est la bonne habitude à prendre, mais là tout
est dans le même Thread.

D'autre part, dans ce que tu as écrit, la variable "del" est la même tout le
temps, crée la une seule fois en dehors de "private void timer1_Tick". Comme
tu la crées à chaque clic, ça bouffe de la mémoire.
Pareil pour l'objet paramètre "paramList". Une méthode pour ne pas avoir à
le créer à chaque fois est de prendre une variable globale créée une fois
pour toute, comme pour "del".

Bien sûr, tout celà ne règle pas le problème du GC un peu lent... Note tout
de même que, dans la partie construite par ton IDE, la fonction
InitializeComponents prend la peine de créer tous les contrôles (qui sont
des "objects"), et de les supprimer aussi à la fin par "Dispose()". Il
faudrait trouver un moyen de virer "paramList" après utilisation.





Tu as tout a fais raison. le Delegate n'est pas forcément utile dans ce
cas là. Mais ca me change pas le problème. Le Timer créer de la mémoire
de toute facon rien qu'avec la fonction DateTime.Now.ToLongTimeString().
Et le Garbage collector est incapable de libérer cette mémoire même avec
l'appel de la fonction collect(). Est ce que c'est un bug du
framework ou alors je programme mal!

j'ai le même problème si dans mon timer, j'appel les lignes suivantes

byte[] memory = new byte[10000];
memory.Initialize();
memory = null;

le type byte n'est pas nullable, je ne peut donc pas mettre les 10000
bytes à null!


comment puis-je indiquer que garbage collector qu'il peut libérer la
mémoire. Qu'il la libère de suite ou toutes les minutes ce n'est pas
grave. Mais il dois la libérer c'est son job!

PS: j'ai tester ce petit programme avec le framework 1.1 et 2.0
Avatar
PeeF
> Une question en passant.

J'ai une form avec un label. Au chargement de la form, un thread est lancé
et doit changer la propriété Text du label. Pour celà, j'utilise une
délégate, j'ai bon ?




A partir du moment ou c'est un autre Thread qui doit mettre à jour un
contrôle de la Form, oui.
Quelque part pr là: http://msdn2.microsoft.com/en-us/library/zyzhdc6b.aspx
il y a un exemple de la méthode Invoke pour mettre à jour une ListBox d'une
Form depuis un autre Thread. C'est iningliche.
Avatar
Delf
Alexandre Czysz a écrit :

Qu'il la libère de suite ou toutes les minutes ce n'est pas
grave. Mais il dois la libérer c'est son job!



Je crois qu'il libère la mémoire si nécessaire...

--
Delf