Partage
  • Partager sur Facebook
  • Partager sur Twitter

.Net threads

Sujet résolu
Anonyme
    14 septembre 2017 à 18:42:05

    Bonsoir,

    Dans le cadre d'un projet communautaire, je réalise un logiciel en C# où j'ai besoin d'envoyer une datagram à environ 150/200 serveurs.

    La fonction ci-dessous est appelé lorsqu'un utilisateur sélectionne un nouvel onglet, j'utilise deux thread imbriqués car j'utilise la fonction d'attente WaitAll dans ma classe ServerQuery.

    1) Est-ce une bonne façon de faire selon vous ?

    2) Mon problème est que si l'utilisateur change d'onglet très rapidement (flood) pendant un bon nombre de fois, le programme va crasher (du fait du trop grand nombre de thread créer à un instant T j'imagine). Pour pallier à ce problème, j'ai pensé créer un threadpool et à chaque fois que la fonction est appelé je stop les threads et je vide le pool. Encore une fois, selon-vous, est-ce une bonne façon de faire ou existe-il quelques choses de plus performant et adapté à mes besoins ?

    Je vous remercie par avance !

    Code :

    private async void tabControlServer_Selected(object sender, TabControlEventArgs e)
            {
                listViewPlayers.Items.Clear();
                listViewRules.Items.Clear();
    
                this.labelAddressValue.Text = "-";
                this.labelLanguageValue.Text = "-";
                this.labelModeValue.Text = "-";
                this.labelPingValue.Text = "-";
                this.labelPlayersValue.Text = "-";
    
                TabPage current = (sender as TabControl).SelectedTab;
    
                var listView = current.Controls.Cast<ListView>().FirstOrDefault(x => x is ListView);
    
                listView.Items.Clear();
    
                var serversList = await SampUtils.GetServerList(SampUtils.E_TYPE_LIST.LIST_FAVOURITES);
    
                var splittedList = serversList.Split('\n');
    
                 new Thread(() =>
                 {
                     foreach (var ipPort in splittedList)
                     {
                         string[] splitIp = ipPort.Split(':');
    
                         if (splitIp.Length == 2)
                         {
                             new Thread(() =>
                             {
                                using (ServerQuery query = new ServerQuery(splitIp[0], Int32.Parse(splitIp[1])))
                                {
                                    Byte[] buffer = SampUtils.__buildPacket(splitIp[0], Int32.Parse(splitIp[1]), 'i');
    
                                    var result = query.SendReceive(buffer);
    
                                    var formattedResult = SampUtils.__parseResponse(result);
    
                                    if (formattedResult.Length == 6)
                                    {
                                        if (listView.InvokeRequired)
                                        {
                                            listView.BeginInvoke(new MethodInvoker(delegate ()
                                            {
                                                ListViewItem item = new ListViewItem(new string[] { formattedResult[0], formattedResult[3], formattedResult[1] + "/" + formattedResult[2], "-", formattedResult[4], formattedResult[5] });
                                                item.Tag = ipPort;
                                                listView.Items.Add(item);
                                            }));
                                        }
                                    }
                                 }
    
                             }).Start();
                             Thread.Sleep(20);
                         }
                     }
                 }).Start();
            }



    • Partager sur Facebook
    • Partager sur Twitter
      14 septembre 2017 à 19:20:30

      >une datagram à environ 150/200 serveurs.

      Je pense qu'on a déjà largement franchi le seuil en nombre de destinataire où l'envoie en point à point par datagram est une vaste plaisanterie.

      Pensez rapidement à vous renseignez sur les envois multi-cast et autres protocoles, RSVP par exemple.

      >1) Est-ce une bonne façon de faire selon vous ?

      NON, un thread ça cout très cher à créer et faut pas en faire des milliers en même temps.

      >du fait du trop grand nombre de thread créer à un instant T j'imagine

      La divination est au cursus des études d'informatique maintenant ???

      N'imaginez pas, utilisez les outils à votre dispositions, comme les débogueurs, les messages du Runtime .NET, les fichiers de dumps, etc...

      >j'ai pensé créer un threadpool

      Bien, les concepteurs de .NET aussi, il y a bien longtemps (au cas l'idée saugrenu d'inventer une roue carrée pop dans ton esprit)

      https://msdn.microsoft.com/fr-fr/library/system.threading.threadpool%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

      > et à chaque fois que la fonction est appelé je stop les threads et je vide le pool.

      C'est absolument pas comme cela que fonction le ThreadPool de .NET, et heureusement.

      >Encore une fois, selon-vous, est-ce une bonne façon de faire

      Non

      >ou existe-il quelques choses de plus performant et adapté à mes besoins ?

      Oui, utilisez correctement les outils que .NET met à votre disposition. (Et des protoles adaptés aussi)

      Une expression lambda de plus de 35 lignes, en plus avec une autre expression lambda incluse asynchrone (new Thread) dedans, WTF, c'est à partir de combien de ligne (et de complexité cyclomatique) que vous pensez à en faire une méthode ???

      Non, parce qu'en plus, elle a un vrai sens en terme de méthode ou de classe, donc avoir un petit nom pour elle, ça serait sympa. "A votre Bon Coeur, S'il vous plait, Merci"

      Regardez les exemples d'utilisation des ThreadPool pour voir comment ça fonctionne.

      P.S.: La condition ligne 42, elle bien drôle celle-là. :D

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
      Anonyme
        14 septembre 2017 à 19:25:16

        Je vais me tourner vers du multicast, merci.

        -
        Edité par Anonyme 14 septembre 2017 à 19:36:55

        • Partager sur Facebook
        • Partager sur Twitter
          14 septembre 2017 à 19:40:19

          Hello,

          Comme dit bacelar c'est vraiment pas très joli à regarder, va peut-être falloir maroufler un peu ce code pour qu'il soit plus agréable à lire et à comprendre, surtout si c'est un projet communautaire.

          J'ai du mal à comprendre le lien entre le problème de départ envoyer un datagram à plusieurs serveurs, pour ça on peut utiliser le multicast, je te laisse te renseigner un peu là dessus, et l'histoire des onglets et des threads ? 

          Essaye de jeter un oeil aux trucs qu'on te conseille, sinon dis nous en plus parce que là c'est quand même un beau sac de noeuds :D

          • Partager sur Facebook
          • Partager sur Twitter
          Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
          Anonyme
            14 septembre 2017 à 19:47:59

            Il s'agit d'un "launcher", il permettra d'afficher une liste de serveurs avec des informations, retournées par ces derniers, telles que le nom, le nombre de joueurs, ...

            Lorsqu'un un utilisateur change d'onglet, j'envoi un grand nombre de datagrams en direction des serveurs et ce créant un thread pour chaque envoi.. J'ai rapidement constaté que ce n'était pas une méthode viable avec le profiler notamment.

            Au niveau du code, tous le projet est très bien ordonné (classes, méthodes, ...), c'est juste que je viens tout juste de mettre en place ça et avant d'ordonner le code je préfère m'assurer du bon fonctionnement du programme (sans exagération bien sur, là le bout de code reste tout à fait lisible mais il sera tout de même revu une fois terminé).

            Je vais me renseigner sur le fonctionnement du multicast, merci :)

            -
            Edité par Anonyme 14 septembre 2017 à 19:48:28

            • Partager sur Facebook
            • Partager sur Twitter
              14 septembre 2017 à 21:54:55

              Ok, je comprends mieux.

              Un conseil du coup, c'est plus simple que le serveur broadcast les infos à tous les clients abonnés plutôt que d'avoir tous les clients abonnés qui récupèrent les infos du serveur.  

              Et par plus simple je veux dire, plus propre et plus performant aussi. Le serveur diffuse son statut et les clients abonnés vont le recevoir, ça évite tes soucis de "spam". Tu peux par exemple utiliser la technologie SignalR pour faire ça. Si un client poll les 150 serveurs toutes les 30s pour avoir le statut à jour du serveur je n'imagine pas la charge que ça représente avec de multiples clients.
              • Partager sur Facebook
              • Partager sur Twitter
              Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
              Anonyme
                14 septembre 2017 à 22:58:16

                Re,

                Merci pour ta réponse, malheureusement je n'ai aucun accès aux serveurs, je t'explique pourquoi :

                En faite il s'agit de base d'un mod multijoueur développer en "reverse engineering" sur un ancien jeu, ce mod permet à n'importe qui d’héberger des serveurs et d'y accueillir des joueurs. Le développement du mod multijoueur étant arrêté (et non open-source), j'aimerais reproduire le launcher officiel mais en y apportant des fonctionnalités comme la possibilité d'installer des mods.

                Je reçois donc uniquement une liste d'ip que je récupère en HTTP mais je n'ai pas accès au code source côté serveur :/

                • Partager sur Facebook
                • Partager sur Twitter
                  14 septembre 2017 à 23:27:47

                  Ok, mais garde à l'esprit que c'est pas la fête pour un client d'interroger une liste de serveur en continue pour avoir leur état et c'est pas la fête pour un serveur d'avoir une liste de client qui viennent lui demander comment il va en continue non plus :D
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
                  Anonyme
                    14 septembre 2017 à 23:31:11

                    Oui j'en suis conscient après seul le serveur sélectionné (dans la ListView) sera actualisé toutes les x secondes, la totalité des serveurs seront interrogés qu'une seule fois par changement d'onglet. 

                    • Partager sur Facebook
                    • Partager sur Twitter

                    .Net threads

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown