1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2011
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2011
    Messages : 37
    Points : 46
    Points
    46

    Par défaut Architecture réception UDP => Freeze IHM

    Bonjour,

    J'ai une classe permettant de recevoir des messages UDP (dans des backgroundworker), et de faire le décodage de ces messages à l'aide d'un dictionnaire définissant ces messages.
    Par la suite, les données sont affichées sur l'IHM à l'aide de Binding. Cette méthode fonctionne, mais lorsque je reçois énormément de données sur un court laps de temps, le temps de décodage freeze mon IHM.
    Pouvez-vous me donnez une analyse critique de ma solution actuelle et/ou me proposer des axes d'amélioration ?

    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
            private         byte[]               m_data;
     
            /// <summary>
            /// Background worker de récupération des messages
            /// de la liaison ethernet UDP 1
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void bw1_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
     
                while (true)
                {
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        comEth1.Ret(out m_data1); // récupération du message
                        m_bw1.ReportProgress(0, m_data1);
                    }
                }
            }
     
            /// <summary>
            /// Lors d'un changement dans le background worker 1
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void bw1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                lock (lockData)
                {
                    // On renvoi les données
                    Data = (byte[])e.UserState;
                }
            }
     
            /// <summary>
            /// Background worker de récupération des messages
            /// de la liaison ethernet UDP 2
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void bw2_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
     
                while (true)
                {
                    if ((worker.CancellationPending == true))
                    {
                        e.Cancel = true;
                        break;
                    }
                    else
                    {
                        comEth2.Ret(out m_data2); // récupération du message
                        m_bw2.ReportProgress(0, m_data2);
                    }
                }
            }
     
            /// <summary>
            /// Lors d'un changement dans le background worker 2
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void bw2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                lock (lockData)
                {
                    // On renvoi les données
                    Data = (byte[])e.UserState;
                }
            }
     
            /// <summary>
            /// Evénement sur la variable "Data" (des progresschanged) lorsque ses données changent
            /// Reception des messages : Cette fonction se lance à chaque réception d'un message
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Data_changed(object  sender, EventArgs e)
            {
                try
                {
                    byte[] b = Data; // Mettre dans une variable, comme ça, si Data change de valeur en plein milieu de la fonction, pas de problème
                    if (b != null)
                    {
                            // Traitement (assez lourd) sur "b" en fonction de mon dictionnaire de message pour décoder mes messages et les mettre dans une classe des messages sur laquelle les bindings sont réalisées
                    }
                 }
                 catch
                 {
                     ...
                 }
             }
    Je pense mettre le traitement (Data_Changed) dans un backgroundworker mais je ne vois pas trop où le mettre. J'ai aussi regardé les fonctions avec async, mais je ne connais pas trop le fonctionnement.

    Merci d'avance.

    Cordialement

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    juillet 2005
    Messages
    323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : juillet 2005
    Messages : 323
    Points : 757
    Points
    757

    Par défaut

    Bonjour,

    Pour moi un freeze de l'IHM peut rapidement et facilement être évité avec Async/await, c'est pour ça que je te le conseillerais (ca sert à ça en faite). Après c'est vrai que si tu as un backGroundWorker tu pourrais sans doute l'utiliser... et ainsi éviter de mélanger les concepts. Pour le backGroundWorker j'en ai pas fait depuis longtemps... donc je passe mon chemin.

    Si async/await t'intéresse, le principe est d'isolé dans une fonction un longtemps traitement, on va l'appeler Job().
    Puis d'en faire une méthode asynchrone pour ça =>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public Task JobAsync()
    {
        return Task.Run(Job());
    }
    Puis de l'appeler dans un event comme tu le fais =>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private void async Data_changed(object sender, EventArgs e)
    {
        var task = JobAsyn(); //ici le job est lancé.
        await task; //ici j'attend que le job soit terminé mais je rend la main au thread courant (donc celui de l'UI).
        MessageBox("Job terminé");
    }

    J'ai tapé ces lignes rapidement sans rien tester, et j'ai faim ! C'est juste pour te présenter un peu le concept...
    Redis-moi si t'en veux plus

    Bon code,
    J@ck.
    Pas de réponse par MP, merci.

    Penser au ça fait plaisir

  3. #3
    Rédacteur/Modérateur
    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    juillet 2016
    Messages
    846
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Charente Maritime (Poitou Charente)

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

    Informations forums :
    Inscription : juillet 2016
    Messages : 846
    Points : 2 888
    Points
    2 888
    Billets dans le blog
    5

    Par défaut

    Bonjour,

    Citation Envoyé par J@ckHerror Voir le message
    Pour moi un freeze de l'IHM peut rapidement et facilement être évité avec Async/await, c'est pour ça que je te le conseillerais (ca sert à ça en faite). Après c'est vrai que si tu as un backGroundWorker tu pourrais sans doute l'utiliser... et ainsi éviter de mélanger les concepts. Pour le backGroundWorker j'en ai pas fait depuis longtemps... donc je passe mon chemin.
    Attention, async/await, de base, sert à ça quand le temps d'attente est dû à une action passive (attente, par exemple, lecture d'un fichier, réception d'une trame réseau, etc...) et non une action active (traitement). Dans le cas où c'est un traitement il faut utiliser un autre thread pour l'exécution du traitement, et n'utiliser le thread graphique uniquement lorsque c'est nécessaire (mise à jour de l'affichage). Les possibilités sont :


    Dans ton cas, je pense que la méthode la plus simple est de réaliser le traitement dans un Task (cf. mon premier article pour savoir comment faire), car cela utilise le pool de threads et donc sera sans doute plus léger que la création de nouveau threads à chaque message reçu, et sera sans doute plus simple aussi à mettre en œuvre et plus clair que l'utilisation d'un backgroundworker (mais là, il faudrait une vision globale pour pouvoir l'affirmer).
    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

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    octobre 2011
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : octobre 2011
    Messages : 37
    Points : 46
    Points
    46

    Par défaut

    Merci pour ces explications.

    Du coup, j'ai mis mon traitement dans un backgroundworker avec des progresschanged pour faire la liaison avec mon IHM.

    Ca a l'air de fonctionner, reste à voir avec de grandes quantités de données.

    A+.

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

Discussions similaires

  1. Réception UDP, passer un tour de boucle
    Par R00t_infinity dans le forum Langage
    Réponses: 4
    Dernier message: 17/12/2013, 11h49
  2. Réception UDP avec des sockets
    Par Gregory_007 dans le forum Réseau
    Réponses: 18
    Dernier message: 20/07/2012, 02h49
  3. [SWT] Freeze IHM avec le composant Tree
    Par ensi_en dans le forum SWT/JFace
    Réponses: 9
    Dernier message: 03/05/2010, 15h50
  4. pb réception UDP avec transfert rapide
    Par loup_precaire dans le forum Réseau
    Réponses: 4
    Dernier message: 23/03/2009, 21h22
  5. Réception UDP et test de chaine
    Par molotov dans le forum Débuter
    Réponses: 6
    Dernier message: 28/03/2008, 17h14

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