IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langages Discussion :

C# problème de flickering (freeze) lors de la mise à jour d'une listBox


Sujet :

Langages

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2017
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Août 2017
    Messages : 21
    Points : 6
    Points
    6
    Par défaut C# problème de flickering (freeze) lors de la mise à jour d'une listBox
    Bonjour à tous,
    mon programme récupère des datas via une carte d'acquisition. J'ai mis en place un événement qui s'active dès la réception d'une des datas. Les datas sont envoyées très rapidement (de l'ordre de la ms). J'affiche sur ma listbox les différentes datas qui sont récupérées. Chaque data possède un identifiant unique que je place dans une ligne précise de ma listbox. Je met à jour la ligne de ma listbox concernée lors de la réception d'une data
    Voici mon problème :
    Lorsqu'il y a qu'une data qui est reçu => pas de problème, ma listbox est correctement mise à jour sans freeze ni clignotement.
    En revanche, plus je reçoit de datas, plus le contenu de ma listbox freeze et lorsque je reçois 12 datas, je ne vois pratiquement plus rien.
    J'ai tenté de faire un doublebuffered sur ma listbox mais cela n'a rien changé.
    J'ai tenté le code ci-dessous. Résultat : ça ne freeze plus en revanche le temps de réponse de l'affichage est beaucoup trop long et par conséquent, le traitement que je fais derrière ne suit plus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    public class DoubleBufferedListBox : System.Windows.Forms.ListBox
        {
            public DoubleBufferedListBox()
            {
                this.SetStyle(
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.UserPaint,
                    true);
                this.DrawMode = DrawMode.OwnerDrawFixed;
            }
     
            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                if (this.Items.Count > 0)
                {
                    e.DrawBackground();
                    e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font, new SolidBrush(this.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y));
                }
                base.OnDrawItem(e);
            }
     
            protected override void OnPaint(PaintEventArgs e)
            {
               Region iRegion = new Region(e.ClipRectangle);
                e.Graphics.FillRegion(new SolidBrush(this.BackColor), iRegion);
                if (this.Items.Count > 0)
                {
                    for (int i = 0; i < this.Items.Count; ++i)
                    {
                        System.Drawing.Rectangle irect = this.GetItemRectangle(i);
                        if (e.ClipRectangle.IntersectsWith(irect))
                        {
                            if ((this.SelectionMode == SelectionMode.One && this.SelectedIndex == i)
                            || (this.SelectionMode == SelectionMode.MultiSimple && this.SelectedIndices.Contains(i))
                            || (this.SelectionMode == SelectionMode.MultiExtended && this.SelectedIndices.Contains(i)))
                            {
                                OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font,
                                    irect, i,
                                    DrawItemState.Selected, this.ForeColor,
                                    this.BackColor));
                            }
                            else
                            {
                                OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font,
                                    irect, i,
                                    DrawItemState.Default, this.ForeColor,
                                    this.BackColor));
                            }
                            iRegion.Complement(irect);
                        }
                    }
                }
                base.OnPaint(e);
            }
        }
    Auriez-vous des idées pour palier au problème ?

    D'avance, je vous en remercie.

    Voici le code permettant la mise à jour de ma listebox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
            public void Affichage(AcquisitionTrameEventArgs Acq)
            {
                int index = 0;
                switch (Monitoring_type)
                {
                    case "Monitoring_statique":
                        if (checkList(Acq.myEventAcquisition.Id))
                        {
                            int i;
                            for (i = 0; i < Liste_ID.Count; i++)
                            {
                                if (Liste_ID[i] == Acq.myEventAcquisition.Id)
                                {
                                    index = Liste_ID.IndexOf(Acq.myEventAcquisition.Id);
                                    break;
                                }
                            }
                            listBox_TrameCAN.Items.RemoveAt(index);
                            listBox_TrameCAN.BeginUpdate();
                            listBox_TrameCAN.Items.Insert(index, index + "\t\t" +
                                                                    Acq.myEventAcquisition.Time + "\t\t" +
                                                                    Acq.myEventAcquisition.Id.ToString("X") + "\t\t" +
                                                                    Acq.myEventAcquisition.Data[0].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[1].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[2].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[3].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[4].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[5].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[6].ToString("X") + "   " +
                                                                    Acq.myEventAcquisition.Data[7].ToString("X"));
                            listBox_TrameCAN.EndUpdate();
                        }
                        //On ajoute l'identifiant à la liste
                        else
                        {
                            listBox_TrameCAN.BeginUpdate();
                            listBox_TrameCAN.Items.Insert(Liste_ID.Count,
                                                                            Acq.myEventAcquisition.Time + "\t\t" +
                                                                            Acq.myEventAcquisition.Id.ToString("X") + "\t\t" +
                                                                            Acq.myEventAcquisition.Data[0].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[1].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[2].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[3].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[4].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[5].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[6].ToString("X") + "   " +
                                                                            Acq.myEventAcquisition.Data[7].ToString("X"));
                            listBox_TrameCAN.EndUpdate();
                            Liste_ID.Add(Acq.myEventAcquisition.Id);
                            Liste_ID.Sort();
     
                            for (int i = 0; i < Liste_ID.Count; i++)
                            {
                                if (Liste_ID.ElementAt(i) == Acq.myEventAcquisition.Id)
                                    ListReceptionTrameMemorisee.Insert(i, Acq.myEventAcquisition);
                            }
                        }
                        break;
                    default:
                        MessageBox.Show("Pas codé pour l'instant");
                        break;
                }
            }

  2. #2
    Expert confirmé
    Avatar de wallace1
    Homme Profil pro
    Administrateur systèmes
    Inscrit en
    Octobre 2008
    Messages
    1 966
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Administrateur systèmes
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 966
    Points : 4 005
    Points
    4 005
    Billets dans le blog
    7
    Par défaut
    bonjour,

    Peut être y a t il un élément de réponse ici :
    https://social.msdn.microsoft.com/Fo...=csharpgeneral

    @+

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2017
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Août 2017
    Messages : 21
    Points : 6
    Points
    6
    Par défaut
    J'ai regardé le lien, j'ai testé la plupart des solutions proposées malheureusement sans succès. Et je suis retombé sur le code que j'avais écrit. Cette fonction supprime totalement les scintillements mais le temps de mise à jour des datas reçus est très long (quelques secondes de réaction). Si vous avez une idée du problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    public class DoubleBufferedListBox : System.Windows.Forms.ListBox
        {
            public DoubleBufferedListBox()
            {
                this.SetStyle(
                    ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.UserPaint,
                    true);
                this.DrawMode = DrawMode.OwnerDrawFixed;
            }
     
            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                if (this.Items.Count > 0)
                {
                    e.DrawBackground();
                    e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font, new SolidBrush(this.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y));
                }
                base.OnDrawItem(e);
            }
     
            protected override void OnPaint(PaintEventArgs e)
            {
               Region iRegion = new Region(e.ClipRectangle);
                e.Graphics.FillRegion(new SolidBrush(this.BackColor), iRegion);
                if (this.Items.Count > 0)
                {
                    for (int i = 0; i < this.Items.Count; ++i)
                    {
                        System.Drawing.Rectangle irect = this.GetItemRectangle(i);
                        if (e.ClipRectangle.IntersectsWith(irect))
                        {
                            if ((this.SelectionMode == SelectionMode.One && this.SelectedIndex == i)
                            || (this.SelectionMode == SelectionMode.MultiSimple && this.SelectedIndices.Contains(i))
                            || (this.SelectionMode == SelectionMode.MultiExtended && this.SelectedIndices.Contains(i)))
                            {
                                OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font,
                                    irect, i,
                                    DrawItemState.Selected, this.ForeColor,
                                    this.BackColor));
                            }
                            else
                            {
                                OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font,
                                    irect, i,
                                    DrawItemState.Default, this.ForeColor,
                                    this.BackColor));
                            }
                            iRegion.Complement(irect);
                        }
                    }
                }
                base.OnPaint(e);
            }
        }

  4. #4
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour

    Tout ton code de mise à jour doit se faire dans un tampon "temp" (ArrayList ,List<Of >)....
    Une fois l'Array ou le List<Of> mis à jour tu utilises la méthode ListBox.AddRange (temp),elle est plus rapide que la methode ListBox.Add concernant la peinture du contrôle...

    MSDN LIB Fr:
    Le meilleur moyen d'ajouter plusieurs éléments à ListBox consiste à utiliser la méthode AddRange de la classe ListBox.ObjectCollection (à l'aide de la propriété Items de ListBox). Cela vous permet d'ajouter un tableau d'éléments à la liste en une seule opération
    bon code...

  5. #5
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 758
    Points : 10 541
    Points
    10 541
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Simple question : combien d'éléments peut contenir ta liste ?

    Car s'il y en a beaucoup, il y a quelques problèmes d'algorithmie dans ton code qui pourrait expliquer les ralentissements.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for (i = 0; i < Liste_ID.Count; i++)
    {
       if (Liste_ID[i] == Acq.myEventAcquisition.Id)
       {
          index = Liste_ID.IndexOf(Acq.myEventAcquisition.Id);
          break;
       }
    }
    Peut se simplifier par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    = Liste_ID.IndexOf(Acq.myEventAcquisition.Id);

    Il y a de forte chance pour que la fonction checkList parcourt déjà la liste Liste_ID. Donc si l'ID est présent, tu la parcours 2 fois :
    • une première fois pour savoir si l'élément est présent ;
    • une seconde pour récupérer l'index de l'élément.

    Tout pourrait être fait en une seule passe.

    De même ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    listBox_TrameCAN.Items.RemoveAt(index);
    listBox_TrameCAN.BeginUpdate();
    j'inverserai les deux lignes.

    Ensuite, j'ai constaté que la liste ListReceptionTrameMemorisee était mise à jour lors de l'ajout d'un nouvel élément, mais n'était pas mise à jour lors de la mise à jour d'un élément existant. Normal ?

    Enfin, dans le cas de la mise à jour d'un élément, plutôt que de le supprimer et d'en créer un nouveau, je metterais à jour l'élément existant.

    Sinon, s'il s'agit bien de la fréquence des données qui posent problème (a priori, il y a une nouvelle données de l'ordre de la ms), alors tu peux bufferiser l'arrivée des trames et ensuite mettre à jour la listbox régulièrement (par exemple, via un timer).
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2017
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Août 2017
    Messages : 21
    Points : 6
    Points
    6
    Par défaut
    C'est tout bon, j'ai trouvé la solution en suivant vos conseils.
    J'ai créé une liste de string contenant toutes mes datas à afficher. Puis, par le biais d'un Timer, je met à jour ma listbox en actualisant toutes mes lignes. Avec cette méthode, plus de Freeze, et plus de temps de latence.


    Merci beaucoup pour vos conseils toujours aussi utiles et pertinent.

    Ci-dessous, mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
                             if (checkList(Acq.myEventAcquisition.Id))
                        {
                            Timer_Affichage.Enabled = true;
                            index = Liste_ID.IndexOf(Acq.myEventAcquisition.Id);
                            Liste_Trame[index] = Acq.myEventAcquisition.Time + "\t\t" +
                                                 Acq.myEventAcquisition.Id.ToString("X") + "\t\t\t" +
                                                 Acq.myEventAcquisition.Data[0].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[1].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[2].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[3].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[4].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[5].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[6].ToString("X") + "   " +
                                                 Acq.myEventAcquisition.Data[7].ToString("X");
                        }
                        //On ajoute l'identifiant à la liste
                        else
                        {
                            Liste_Trame.Insert(Liste_ID.Count, Acq.myEventAcquisition.Time + "\t\t" +
                                                                Acq.myEventAcquisition.Id.ToString("X") + "\t\t\t" +
                                                                Acq.myEventAcquisition.Data[0].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[1].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[2].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[3].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[4].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[5].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[6].ToString("X") + "   " +
                                                                Acq.myEventAcquisition.Data[7].ToString("X"));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            private void Timer_Affichage_Tick(object sender, EventArgs Acq)
            {
                listBox_TrameCAN.BeginUpdate();
                listBox_TrameCAN.Items.Clear();
                listBox_TrameCAN.Items.AddRange(Liste_Trame.ToArray());
                listBox_TrameCAN.EndUpdate();
            }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Code lors de la mise à jour d'une cellule
    Par Prof_Matches dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 06/01/2012, 12h07
  2. Réponses: 12
    Dernier message: 14/06/2011, 09h04
  3. Réponses: 0
    Dernier message: 14/04/2010, 11h32
  4. [AC-2003] Erreur lors de la mise à jour d'une table SQL Server 2008
    Par suziwan dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 14/12/2009, 22h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo