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

Développement Windows Discussion :

c# quelle solution pour rafraichir une fenetre pour une application client-serveur [Débutant]


Sujet :

Développement Windows

  1. #1
    Membre éprouvé
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 449
    Points : 991
    Points
    991
    Par défaut c# quelle solution pour rafraichir une fenetre pour une application client-serveur
    Bonjour, j'ai un peu la tête encombrée à force de lire, entre Français, Anglais... des réponses qui datent de plusieurs années...

    Bref, donc je fais une application client-serveur, j'ai déjà sommairement fait un serveur (en java.nio2... qui ira sur un pc linux) , et un client pour windows. Les deux se parlent mais n'ont pour le moment pas grand chose à se dire car je n'avais pas encore fait l'IHM, ce qui est maintenant fait. L'idée c'est que le client demande en boucle des informations, et que le serveur lui renvoie (comme par exemple l'usage du processeur distant). J'ai utilisant du non bloquant des deux cotés donc sur ce point pas de soucis.

    Mais c'est niveau implantation que je sèche totalement pour opter pour la meilleure solution possible. Je n'ai jamais abordé trop le multi proc/thread sur c#, j'en ai fait sous python mais je ne retrouve pas mes marques.
    Sous Python une de mes applis lance 3 cores car elles travaillent vraiment en parallèle (une surveille le lan, la seconde un vpn (ping, port ouvert etc etc) et la troisième gère des appels déclenchant pour des plugins). Et la principale a un multi queue, tandis qu'il y a des pipes entre le core du vpn et celle des plugins plus un autre mais je ne sais plus ou, ça fait un moment. Bref je me suis dit que j'allais faire la même chose sous c#... mais je me suis cassé les dents sur le fait que les forms ne peuvent pas être facilement modifiés depuis une autre source que le thread qui les a lancé.

    Donc j'ai pas mal de questions:
    - Finalement est ce que la programmation parallèle se justifierait là pour proposer le meilleur temps de réaction possible entre le dialogue client-serveur et le refresh de la fenetre ?
    - Est ce que je devrais considérer au final cela comme un même bloc ?
    - Est il vrai que de passer par des invokes + délégués a un cout non négligeable ?? j'ai vu que c'est 49ns pour un invoke, dans mon cas ça serait préjudiciable ?
    - Comment établir des pipes entre les process ? Des objets consacrés ?
    - Au final c'est quoi la différence entre async et le multithhreading j'ai lu le topic sur le forum qui date de 2013, mais j'ai du mal... async est sensé être basés sur TPL non ? Donc ça devrait être du // ? Si c'est le cas pourquoi je ne vois rien dans l'observateur de thread etc ? En effet j'ai fait un banal truc via async, je compte jusqu'à un million et j'affiche dans la textbox de la fenetre principale... Je ne vois ni thread ni process supplémentaire, juste dans module une dll qui s'ajoute.

    Et bref surtout LA question au final c'est quoi le mieux ?? Async ou Les Threads dans un cas comme ça ? Cette application est vraiment dépendante du serveur, c'est une interface locale pour lire toutes les informations du serveur y compris sa configuration, la paramétrer, gérer des fichiers etc. C'est un projet ambitieux, j'en ai conscience, mais j'ai l'habitude de lire des centaines de forums, des tutos, etc etc pour progresser... jusque que là je suis à un embranchement et je cale pour choisir.

    Merci d'avance.

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    ca fait beaucoup de questions ^^

    async await, c'est censé être pratique, mais ce n'est pas forcément du multithreading

    le multithreading comme je l'explique souvent, c'est comme ce qu'on voit en debug pas à pas, la ligne jaune avance d'une ligne à chaque F10
    en multithreading il y a l'équivalent de plusieurs lignes jaunes qui sont à des endroits différents du code
    quand elles sont au même endroit ca peut poser problème , m'enfin je détaillerais les problèmes liés au multithreading si tu ne vois pas de quoi je parle

    l'interface ne peut en effet pas être modifiée par un autre thread que le thread principal
    aussi il y a alors 3 techniques pour remédier à ca
    la 1ère c'est un thread qui va lire les données et remplit des variables/propriétés d'instances
    et un timer sur le thread principal qui vient une ou deux fois par seconde voir ce qui doit être mis à jour (en wpf avec les dependencyobject c'est moins simple)
    la 2ème c'est les invoke
    perso je suis pas contre, le temps passe souvent inaperçu (il est possible de regrouper tout ce qu'on a à faire, surtout qu'il y a des tas de choses comme la classe action qui permet de faire des petites choses regroupables en list(of action))
    après mal utilisé ca peut mener à des blocages de l'appli
    la 3ème c'est async/await
    async await fonctionne sur le même principe que le backgroundworker (ah oui j'ai oublié de parler de lui, c'est bien pratique pour ça)
    quand on passe sur un await le contexte du thread est gardé, mais on sort de la méthode
    ensuite dans certains cas ca reste le thread principal qui traite ce qu'on fait, dans d'autres c'est un thread séparé
    oui le thread principal peut gérer ça, car autant c'est lui qui dessine l'interface, il y a du temps où il ne fait rien, et c'est ce temps qui est utilisé
    une fois le await fini, le code revient à la ligne où il était, le contexte est resynchronisé (variables précédemment déclarées et autres) et du coup on a l'équivalent de 2 méthodes en une
    perso je suis pas fan d'async, on peut arriver à des blocages d'appli aussi si on les utilise mal
    la 4ème en bonus c'est le backgroundworker (bgw)
    c'est une classe qui encapsule tout ce qu'il faut pour du multithreading
    quand on le démarre ca déclenché l'event dowork, qui est sur un thread séparé, on peut appeler la méthode reportprogress et passer une instance de type object, l'event progress est sur le thread principal ce qui permet de modifier l'interface
    le paramètre étant as object ca peut une collection ou une classe qui contient plein de données
    il y a un event completed qui lui aussi permet de passer un paramètre depuis dowork et est sur le thread principal

    après async utilisent le threadpool, le bgw peut etre aussi
    le threadpool c'est une classe qui permet de ne pas perdre de temps à créer des threads, car comme les invoke certains diront que créer un thread prend du temps
    mais à moins d'en lancer 10 par seconde en continu la différence n'est pas visible
    le threadpool créé par défaut un thread par core logique sur le pc, ensuite quand on veut démarrer une task (ce que fait async) ca prend le 1er thread libre, quand il a fini sa tache il la rend au threadpool
    je suis pas fan car on perd la notion de quand ca démarre

    après pour un traitement continu on utilise souvent un thread qui fait un while true avec un thread.sleep
    le while true permet au thread de vivre en continue et de faire le traitement à intervalle plus ou moins régulier
    le thread.sleep permet de ne pas faire que ca, de ne pas bouffer trop de processeur (car un while true sans thread.sleep c'est un core à 100%, alors qu'avec au moins 1ms de pause ca baisse pas mal), et de laisser le temps libre à d'autres threads
    c'est ce qui reste le plus efficace pour des choses à timer et qui se font sur toute la durée d'exécution de l'appli

    async/await c'est plus pour des requetes (attente) + maj de l'interface, et si j'ai bien suivi surtout en réponse à une action de l'utilisateur


    donc tu peux choisir ce que tu veux je pense, dans les cas tu pourras atteindre le résultat souhaité
    après tu ne détailles pas trop ce que tu dois faire (combien de choses différentes, fréquence, volumétrie ...)
    tu ne nous dit pas non plus ce que tu utilises pour dialoguer avec le server

    en bonus le cours de francois dorin (qui va ptete passer par là ^^) sur un peu tout ca
    http://fdorin.developpez.com/tutorie...eadpool/part1/
    il l'a fait y a pas trop longtemps
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre éprouvé
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 449
    Points : 991
    Points
    991
    Par défaut
    1000 Mercis pour ton explication très détaillée !!!
    De bon matin j'ai vu plus clair, je n'ai pas eu le réflexe de lire en premier, mais ce n'est pas perdu pour autant, loin s'en faut. J'ai lu le tutoriel dont tu parles à la fin, mais le soucis c'est qu'en fait avec les évolutions de C# je ne savais vraiment plus ou j'en étais, qu'est ce qui était le plus adapté, qu'est ce qui était "obsolète" au sens on a sorti un jeu d'instruction qui fait mieux pour ce cas de figure là... etc...

    Bon ce matin je me suis retroussé les manches et j'ai fait de deux manières avec un multithread et un multiprocessor, juste pour voir sur un exemple bateau, compter jusqu'à un million et mettre dans la textbox. Avec le système délégué / invoke ça tourne plutot bien , et très vite. La boucle dont tu parles c'est pile poil ce que je voulais faire et que je fais en python en effet.. qu'on voyait aussi en c++ aussi en fait pour l'affichage si je me souviens bien. Je savais par avance que ça serait bloquant d'ou le désir de vouloir passer ça sur un processus parallèle, asynchrone ou multithread... ça en fait des solutions quand même... pas évident. J'ai lu qu'en fait le multithread c'est en fait un système ou l'on accorde une tranche de temps à chaque thread.

    Au niveau des threads en effet je ne vais pas en lancer 150, c'est un point que je n'avais pas songé à aborder. Je vais lancer ma boucle, qui va gérer le core qui s'occupe du dialogue réseau et cette boucle fera les appels toute seule je pense pour rafraichir diverses portions. A la limite je pensais peut être lancer en thread ponctuel la connexion, et si la connexion réussie alors là lancer un autre thread avec la boucle... Je sais pas faut que je vois c'est pas évident.

    Au niveau du détail du programme. Donc le serveur est programmé en java nio2, donc totalement asynchrone si j'ai bien compris (j'en ai bavé pour le faire), l'idée est de recevoir des "commandes", qu'il traite et renvoie... (combien de personnes connectées, usage du processeur, et mettre à jours une liste de fichiers monitorés). Je vais essayer également de le programmer de manière assez évolutive avec des plugins qu'on peut rajouter... (là aussi pas simple), sans redémarrer... pareil coté client. Donc un module sur le core serveur pour rajouter des fonctions, un plugin du coté client qui les exploite, ou même des plugins purement esthétiques coté client. Pour ça que je détaille pas trop car à terme, l'idée c'est de faire pas mal de truc, mais pour le moment je me contente juste en fait de faire deux ossatures mère, serveur / client. Un chargeur de plugin des deux cotés, et le minimum des fonctions qu'il a à faire dès le début.

    Au niveau de la fréquence de rafraichissement à faire je vais voir en fait la gourmandise, permettre même à l'utilisateur de régler son taux de rafraichissement pour réduire l'impact sur les ressources (dans une fourchette prédéfinie par contre). Mais bon dans l'ensemble vu qu'il y a une surveillance de fichier, l'idée c'est quand même d'avoir les informations les plus à jour possible.

    après en écrivant tout cela, je me demande s'il ne me faut pas une boucle pour l'usage principal, et une boucle pour les fonctions secondaires, de manière à ce que la surveillance des fichiers soit garantie, et que de l'autre coté les fonctions annexes recoivent des informations à un autre rythme. Voire un thread par fonction qui a besoin d'être rafraichit ? Je gamberge... après dans tous les cas je veux un client réactif.

    Ah pour donner un contexte plus global qui expliquera mieux. En fait j'ai fait un nas maison sous ubuntu, il n'a donc pas d'écran. J'ai tous mes autres pcs sous windows 10, j'aime pas vraiment les interfaces webs et pas vraiment satisfaire de ce que je peux trouver en cross platform, et ça me donnait un bon support pour programmer en amateur , plus que ce que j'ai jamais fait ( surtout niveau réseau en fait, et même coté ihm vu que j'ai eu déjà fait des ihm dynamiques mais toujours par les interactions utilisateurs, jamais comme ça, puis c'était en java... ) . Alors c'est un peu maso au final quand il me suffit de prendre le controle du nas pour faire ça, ou d'utiliser un de mes scripts pour le monitoring, plus derrière un client ssh.. mais j'avais envie de me faire un truc perso.

    En fait je me fait tellement souvent rembarrer quand je propose des trucs que j'ai fait, ou quand je pose des questions (pas ici en tout cas), que j'avance à tâtons avant de dire ce que j'ai envie de faire... les gens sont toujours à dire "ça sert à rien" au mieux. Je suis pas dans la programmation, je suis electrotechnicien, à la base j'ai choisi ce coté là pour tout ce qui est automatisation, machines.. je comptais faire Mias ayant découvert l'informatique en cours de route (je suis vieux) mais manque de thunes pour payer l'inscription => bts. Alors je me suis lancé à mes heures perdues dans de la programmation pour le plaisir, et quand je me trouve un sujet.. je suis content. J'ai démarré la programmation à faire des hacks pour vbb puis à m'essayer à faire mon propre forum, même si au final il n'a servi qu'à la maison avec diverses modes de page possibles, de la bibliothèque, au calendrier, en passant par les recettes de cuisine, avec des interfaces dédiées. Ca fait un peu inventeur fou mais j'assume ^^. Voila...

    Pour ce qui est du code, en multiprocessing, j'ai testé cette solution... async await je pense avoir compris grace à tes explications, après là ou j'ai pas capté c'est que sur leur tuto l'utilisent via un système de tasks ce qui au final m'amenait malgré tout à passer par un invoke, j'ai essayé sans ce système mais j'ai un processus bloquant sur mon algorithme de connexion au serveur, c'est juste une ébauche basée sur ce que propose ms sur son site, et l'ihm va me permettre de comprendre les derniers points sur lesquels je n'ai pas de certitude niveau compréhension. Ce code est amené à être découpé pour permettre la commande, WaitOne bloque volontairement pour permettre la connexion, donc l'ihm est bloquée si ça n'est pas lancé indépendamment (si je ne me plante pas).

    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
       class Core_copier
        {
            // public
            long ip;                            // IPEndpoint prend un long pour l'ip
            ushort port;
     
     
            // privé
            private static String reponse = String.Empty;
     
     
            // ManualResetEvent permet d'avertir les threads d'évènements
            // 
            private static ManualResetEvent connexionOK = new ManualResetEvent(false);
            private static ManualResetEvent envoiOK = new ManualResetEvent(false);
            private static ManualResetEvent receptionOK = new ManualResetEvent(false);
     
     
            public void connexion()
            {
     
                try
                {
                    IPAddress ipadress = IPAddress.Parse("216.58.208.195");     //216.58.208.195 = google
                    port = 80;
     
                    Console.WriteLine("Tentative de connexion à {0}", ipadress);
                    IPEndPoint remoteEP = new IPEndPoint(ipadress, port);
     
                    Socket sClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     // Type ipv4; stream = connexion 2points; 
                                                                                                                      //sClient.Bind(new IPEndPoint(ipadress, port));                                                     // Bind sur l'ip fournit (ecoute) Erreur concerne les serveurs
     
                    sClient.BeginConnect(remoteEP, new AsyncCallback(ConnexionCallback), sClient);                 // Connexion callback ici permettra de dire que la connexion est bien faite
                    connexionOK.WaitOne();                      // Bloque le thread jusqu'à avoir reçu un signal
     
     
                    //--- Début du dialogue
                    //Envoi
                    Send(sClient, @"GET / HTTP/1.1\r\nHost: www.paperclip.netai.net \r\nConnection: close\r\n\r\n");
                    envoiOK.WaitOne();
     
                    //Reception
                    Receive(sClient);
                    receptionOK.WaitOne();
     
                    Console.WriteLine("Vous avez un message: {0}", reponse);
     
                    //Fermeture du socket
     
                    sClient.Shutdown(SocketShutdown.Both);
                    sClient.Close();
                    Console.WriteLine("Fermé");
     
                }
                catch (Exception e)
                {
                    Console.WriteLine("Erreur de connexion");
                    Console.WriteLine(e.ToString());
                }
     
     
            }
     
     
            //  Indique que la connexion est achevée
            private void ConnexionCallback(IAsyncResult ar)
            {
                try
                {
     
                    // Récupère le socket client depuis l'état
                    Socket sClient = (Socket)ar.AsyncState;                 // Cast (conversion explicite)
                                                                            // C'est obligatoire pour les conversions qiu ne peuvent pas se faire sans perte de données
                                                                            // Complete la connexion
                                                                            // Met fin à l'attente et indique que la connexion est établit                                                                        
                    sClient.EndConnect(ar);
                    // 
                    Console.WriteLine("Socket connecté sur {0}", sClient.RemoteEndPoint.ToString());   // On indique à l'utilisateur que la connexion est établit avec ...
                    Console.WriteLine(ar.ToString());
     
                    // Signal au thread que l'on peut poursuivre
                    connexionOK.Set();
     
                 }
                catch (Exception e)
                {
                    Console.WriteLine("Erreur de connexion callback");
                    Console.WriteLine(e.ToString());
                }
     
     
     
            }
     
     
            // ---- Fonction d'envoie de données
            private void Send(Socket sClient, string message)
            {
                // Encodage en bytes (obligatoire);
                byte[] byteMessage = Encoding.ASCII.GetBytes(message);
                sClient.BeginSend(byteMessage, 0, byteMessage.Length, 0, new AsyncCallback(SendCallback), sClient);
            }
     
            private void SendCallback(IAsyncResult ar)
            {
                try
                {
                    // Récupère le socket client depuis l'état (cast)
                    Socket sClient = (Socket)ar.AsyncState;
     
                    // On complète le message
                    int bytesSent = sClient.EndSend(ar);
                    Console.WriteLine("Envoyé {0} bytes au serveur", bytesSent);
     
                    // Signal que le message est parti
                    envoiOK.Set();
                }
                catch (Exception e)
                {
                    Console.WriteLine("Erreur de sendcallback");
                    Console.WriteLine(e.ToString());
                }
            }
     
     
            // Fonctions de réception des données
            private void Receive(Socket sClient)
            {
                try
                {
                    // Création du paquet
                    StateObject state = new StateObject();
                    state.workSocket = sClient;
     
                    Console.WriteLine("Debut de reception");
                    // Début de la réception des données
                    sClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);     // 2nd args = offset, 4 = socketflag
                }
                catch (Exception e)
                {
                    Console.WriteLine("Erreur de receive");
                    Console.WriteLine(e.ToString());
                }
     
            }
     
            private void ReceiveCallback(IAsyncResult ar)
            {
                try
                {
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket sClient = state.workSocket;
     
                // Lit les données du remote service
     
                    int bytesRead = sClient.EndReceive(ar);                 // renvoie le nombre de bytes
     
     
                    if (bytesRead > 0)
                    {
                        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                        // Il doit y avoir plus de données donc on va continuer de recevoir
                        sClient.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                    }
                    else
                    {                                      
                        // Toutes les données sont arrivées, on organise la réponse
                        if (state.sb.Length > 1)
                        {                                                
     
                            reponse = state.sb.ToString();
                        }
     
                        // Débloque le thread                
                        receptionOK.Set();
                    }
     
                }
                catch (Exception e)
                {
                    Console.WriteLine("Erreur de receivecb");
                    Console.WriteLine(e.ToString());
                }
            }
        }
    }
    Pour le multiprocess je me suis servi d'un code bateau donc, dès que j'aurais fini la réponse je vais m'occuper d'interfacer tout ça. Et je me suis basé sur ça que j'ai mis dans ma fenêtre principale et un délégué hors classe, que j'ai mis dans le fichier cs de la fenêtre principale: delegate void asyncdelTxtEtat(string text);


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            private void setTextBox(string text)
            {
                if (txtEtat.InvokeRequired)             // Invoke seraot apparemment le fait d'appeler un delégué depuis un autre thread
                {
                    asyncdelTxtEtat machin = new asyncdelTxtEtat( setTextBox );     // On relance la fonction via un délégué
                    Invoke(machin , new object[] { text });
                }
                else
                {
                    txtEtat.Text = text;                // Si l'invoke n'est pas nécessaire on met le texte normalement.
                }
            }
    Après là j'en suis au multiprocess mais c'est juste parce que j'ai testé les deux, le multithread dans la même classe et le multiprocess dans des classes séparées, mais je ne sais pas lequel des deux est le plus adapté.

    ==> Une question encore <== : Pour arrêter la boucle j'utilise un banal booléen comme un "token" (pas sur que ça soit le terme), le while est valable tant qu'à True mais j'ai lu dans les centaines de trucs que je me suis frappé qu'une personne parlait de 'CancellationTokenSource' , ça fait quoi de plus ou de moins ?

    Merci encore, et désolé pour les pavés .



    Edit:
    Je crois avoir pigé async et await grâce à ton exemple sur le debugging même s'il n'était pas directement appliqué. Ca faisait 5-6 fois que je lisais ça "Async peut utiliser Await ou await pour indiquer des points d'interruption. L'opérateur await indique au compilateur que la méthode async ne peut pas continuer au-delà de ce point, tant que le processus asynchrone attendu n'est pas terminé. Entre-temps, le contrôle retourne à l'appelant de la méthode async." sans comprendre.


    Edit 2:

    Bon j'ai réussi avec async aussi finalement... grâce à toi j'ai eu un déclic.

    En fait .... les exemples avec le await que j'avais pris n'étaient pas bon ils servaient juste de timers sur la boucle. Et pour l'exemple ms... en fait j'avais mal compris ou se déroulait réellement le process async... pour moi c'était le thread que tu lançais qui avait la fonction async. Si j'ai bien compris c'est async qui englobe le thread... donc la fonction qu'on lance qui va bouffer du temps n'a pas à être async, c'est celle qui le lancera qui sera async... dans cette fonction on met un await en face du thread qu'on lance.... Toujours si j'ai bien capté... Dans mon exemple pour lancer la connexion à mon serveur ça donne (et donc la méthode StartClient est tout à fait ordinaire):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    private async void connexion(object sender, EventArgs e)  <= mot clé à rajouter async
            {
                Form_GDC gest2Connexion = new Form_GDC();
                DialogResult dr = gest2Connexion.ShowDialog();
     
                if (dr == DialogResult.Cancel) return;            
     
     
    // Partie concernée
                Core connect = new Core();
                await Task.Run(() => connect.StartClient( gest2Connexion.ServChoisi ));
    }
    Là c'était l'exemple sans boucle donc juste pour vérifier ce qu'il se passait si j'essayais de me connecter sur une ip foireuse, un serveur déco, etc etc....

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    les délégués c'est un peu oldschool
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    private void setTextBox(string text)
    {
      if (txtEtat.InvokeRequired)             // Invoke seraot apparemment le fait d'appeler un delégué depuis un autre thread
      {
        Invoke( () => setTextBox(text) ); 
      }
      else
      {
        txtEtat.Text = text;                // Si l'invoke n'est pas nécessaire on met le texte normalement.
      }
    }
    ici c'est une méthode anonyme qu'on repère au () =>
    on peut aussi stocker une méthode anonyme dans une variable de type Action

    une méthode anonyme peut prendre des paramètres de la manière suivante (ici normalement vs va deviner que s est de type string car settextbox demande un string, donc on est pas obligé de préciser le type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      var a =  (s) => setTextBox(s) 
        Invoke(a, s);
    il y a aussi les fonctions anonymes qui elles se rangent dans des Func<T> T étant le type de retour (et donc Func<T1,T2> est une fonction qui prend un T1 en entrée et sort un T2, le dernier type spécifié est la sortie)

    c'était une parenthèse ^^

    après tu n'as pas encore le bon vocabulaire et tu pars un peu dans tous les sens mais tu es sur la bonne piste je pense, enfin tu as l'air de t'amuser et c'est le principal
    ton booléen c'est un flag plutot qu'un token
    et un booléen pour arreter un thread ou annuler quelque ca convient dans la plupart des cas

    le cancellationtokensource c'est ce qui permet d'annuler un traitement asynchrone, ca contient le booléen à tester
    c'est juste que ca permet de faire abstraction entre la source et le traitement, tu n'as pas à chercher où est le booléen, tu transportes le token entre l'appelant et l'appelé, l'appelant peut flagger le token et l'appelé vérifie le token de temps en temps

    concernant le tcp/ip la classe socket est la classe de bas niveau de .net
    en plus simple à utiliser il y a tcplistener (écoute sur un port) et tcpclient (se connecte) (ca utilise la classe socket)
    quand le tcplistener accepte une connexion il instancie un tcpclient aussi côté server, ce qui permet d'avoir la même classe des 2 côtés (réception et envoie)

    ensuite il y a sur ces classes des méthodes synchrones (accept/send/read) et des méthodes asynchrones (begin...)
    avec les méthodes synchrones appeler accept bloque l'exécution jusqu'à qu'un client tente de se connecter, quand c'est le cas ca passe à ligne de code suivante
    avec les méthodes asynchrones appeler beginread demande un callback, ca lance un thread qui va s'occuper d'attendre, et quand ca recoit le callback est appelé (autre méthode qui elle doit appeler endread pour lire les octets)
    après avoir appelé end* il faut relancer un begin* sur le même callback, ce qui fait qu'une acceptation refait une demande d'attente d'acceptation pour le suivant etc...)
    quand on choisit les méthodes synchrones en général on utilise un thread qui while true (read / traitement)
    quand on choisit les méthodes asynchrones ca se débrouille
    mais dans les 2 cas je ne vois pas ce qu'un manualresetevent viendrait faire là ...

    je vois pas trop ce que tu appelles multiprocess, pour moi multiprocess c'est lancer plusieurs exe, au sein d'un seul ce n'est que du multithreading


    pour le system de plugin à la volée il y a des solutions efficaces aussi
    il est même possible que le server distribue des dll à utiliser à n'importe quel moment

    essaye de structurer un peu plus ton propos si tu peux (dit il après avoir digressé ^^)

    et tu te fais rembarrer par qui ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    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 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Comme Pol63 a déjà dit beaucoup de choses, je me contenterai de donner mon avis sur la dernière question.

    Citation Envoyé par daerlnaxe Voir le message
    Et bref surtout LA question au final c'est quoi le mieux ?? Async ou Les Threads dans un cas comme ça ? Cette application est vraiment dépendante du serveur, c'est une interface locale pour lire toutes les informations du serveur y compris sa configuration, la paramétrer, gérer des fichiers etc. C'est un projet ambitieux, j'en ai conscience, mais j'ai l'habitude de lire des centaines de forums, des tutos, etc etc pour progresser... jusque que là je suis à un embranchement et je cale pour choisir.
    Si j'ai bien compris, les traitements longs sont issus d'attente de la part du serveur suite à l'envoi d'une requête. Du coup, si les traitements des données reçues sont simples et rapides, alors l'utilisation de async/await est appropriée. C'est en effet assez simple à mettre en oeuvre et permet d'avoir un code facile à maintenir car gardant un look "séquentiel".
    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
    Membre éprouvé
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 449
    Points : 991
    Points
    991
    Par défaut
    Merci pour les réponses.

    @Pol63 merci pour ta parenthèse je suis très content d'en bénéficier.
    Je vais voir aussi pour les anonymes, j'ai fait des génériques mais c'est vrai que j'ai pas réfléchi à ça et en effet niveau jargon ce n'est pas encore ça... d'ailleurs pour le multiprocess, je parlais multiprocessing mais je suis pas sur de pas me louper au final.. je vais dire programmation parallèle, je devrais moins me louper.

    Pour ce qui est des manuelsresetevent c'était dans le code proposé par microsoft sur leur site, et j'avoue avoir pas mal de mal avec en fait au niveau des exceptions.
    Le waitone semble ici être utile pour permettre une temporisation, le temps que la connexion se fasse, du moins je l'ai compris ainsi. Je suis en train de me pencher sur ça justement au niveau des exceptions, mais bon j'ai un soucis qui fausse je pense que je ne lance pas un multi tache sur une boucle mais une simple en asynchrone, donc je vais aller voir les pools.. donc peut être que je me trompe sur l'interprétation. Toujours est il que si je le lève ça ne laisse pas le temps pour une connexion avec cet algorithme proposé, après j'avais songé mettrre une boucle avec un timer, lever ça... si le résultat débouche sur une erreur on sort, si le résultat débouche sur une connexion et sans ça on attend sur un timer. J'ai testé rapidement ça fonctionne mais là ou je suis incertain c'est que c'est altéré par cette histoire de monothread asynchrone vu que je voulais lancer autant de thread que de serveurs à tester (pas impossible que je le mette sur les autres machines de la maison vu que c'est en java coté serveur au moins j'ai pas à me soucier pour la compilation) je me suis aperçu que ça les testait un par un (ou limiter le nombre d'exécution parallèles.. j'ai conscience que je m'emmele encore sur le jargon grrrr.. donc voir avec des pools, mais malgré tout ne pas tester à la suite les uns des autres).


    @François Dorin, merci pour ta réponse. En fait je ne sais pas vraiment comment ça va se passer par avance, logiquement en effet ce devrait être assez rapide. Merci ça me permet de me positionner pour savoir.

    Pour ce qui est de me faire jareter ben le forum d'OC j'avais posé une question il y a un moment au sujet je crois d'un tuto là bas car je ne pigeais pas un truc, j'ai pas compris si j'avais mis les pieds dans une guerre locale mais je me suis fait répondre que de toute façon ça servait à rien et que je perdais mon temps... une autre question cette fois sur mon code le mec me répond que je fais de la daube sans m'expliquer quoique ce soit, quand on est autodidacte ça avance sacrément. Récemment j'ai fait donc un programme python qui monitoring le vpn sous ubuntu, avec gestion de plusieurs fournisseurs de vpn, forwarding etc etc... en gros plus grand chose à faire une fois lancé il gère au mieux selon ce qu'on souhaite au niveau de la config, ça s'appuie sur openvpn directement et pas mal d'instructions natives et non pas simplement par exemple lancer un ping via un subprocess... les gains sont énormes mine de rien en rapidité.. Même la connexion sous openvpn me prend 1seconde alors que sous network manager avec nmcli je devais être à dix fois plus... bref j'ai vraiment pas mal bossé dessus.. on me répond que ça sert à rien qu'il faut juste se connecter sous openvpn et puis que c'est tout, et que je serais jamais capable de faire quoique ce soit avec mon appli... bon sympa... sachant que cette appli je l'ai fait car le vpn me rejetait de longue, avait des flats... là tout se gère automatiquement, plus jamais les fesses à l'air et en plus ça gère un killswitch donc bon ça fait plaisir surtout que les outils sous ubuntu j'ai pas trouvé ce que je cherchais, des scripts à droite et à gauche en bash, pas aussi bien en tout cas.. du coup j'ai même pas publié plus loin qu'une alpha de base.

    Et hier ou avant hier galérant car je cherchais comment faire une méthode générique qui prenne une classe fasse du traitement en boucle pour chaque champ de la classe et des opérations, et que cette méthode prenne toute classe qui hérite d'une interface qui garantisse une itération bien particulière... le truc simple quoi. En fait ça coincait sur l'itération avec des champs de divers types. Je voulais éviter à la base de passer par une introspection? Mince oublié le nom.. le getproperties en fait car j'ai lu que ça ralentissait bien à hauteur de 5x le travail comparé à d'autres méthodes... bref au moment ou je pose la question, j'avais une réponse possible... passer par un container qui prenait du dynamic et gérer derrière, mais je n'étais pas sur que ça soit une bonne façon de faire, y'a tellement de chose à voir sous c#... j'ai lu plein de choses entre le calcul de ressources le thread safe, les fuites de mémoire... bref du coup un peu la hantise de faire un truc qui soit contreproductif. Donc je pose ma question avec le code que j'ai trouvé en expliquant que j'ai peut être cette option et de demander si c'est une bonne manière de faire, sur un forum anglophone, on me fout du -1 et on me répond qu'on est là pour répondre aux gens qui sont bloqués pas pour répondre sur la meilleure façon de faire... (il est ou l'émoticone de la machoire qui tombe ? ) . Peut être que c'est moi qui débloque mais si la programmation laisse libre de faire comme on veut, si on peut bidouiller pour arriver aux bons résultats c'est pas pour autant que toutes les manières de faire sont bonnes surtout sur c#... sous python je faisais beaucoup moins gaffe, c'est pas typé, simple d'accès c'est rare de faire un truc contreproductif à moins de faire des boucles sur boucles inutiles. Donc voila... sachant que je pose rarement des questions j'use et abuse des moteurs de recherche, sur les forums, sur google, je lis etc etc.. j'essaie de pas être un boulet en fait. En plus d'un truc à l'autre on garde en mémoire pour plus tard donc on apprend même si ça n'est pas en rapport avec ce qu'on cherche dans l'immédiat.. y'a que là ou j'étais paumé, et pour ma méthode générique qui prend n'importe quelle classe ou j'étais pas sur..... bon là elle tourne bien donc apparemment ça doit être correct comme approche.

    Après j'en suis encore au trucs de bases le plus souvent les boucles, les conditionnelles, mais bon voilà après comme tu l'as souligné si c'est pour utiliser des façons encore old school et au risque en prime qu'elle bouffe des ressources pour rien... ou comme ça m'arrive aussi de réinventer la roue (encore si elle est pas carrée au final...).

    Alors je sais que je ponds des pavés et j'en suis désolé ^^ .... MAis très heureux d'avoir trouvé des gens qui m'apportent des réponses, c'est pas évident d'ordinaire !!

  7. #7
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    perso répondre 100x par jour à "comment je fais pour lire un truc d'une fenetre dans un autre" ca me botte pas trop
    par contre quelqu'un qui hésite entre 2 (ou plus) façons de faire ca amène plus de discussion y compris avec d'autres contributeurs et ca permet par exemple de voir d'autres approches

    pour l'introspection c'est reflection
    c'est lent oui quand on fait dans une boucle, mais ca peut être pratique quand même
    et quand bien même on voudrais en faire un fort usage, il reste possible de compiler des expressions basées sur de la reflection pour ne la faire qu'une fois
    dynamic doit d'ailleurs passer un peu de temps à compiler, et perd aussi un peu de perf

    mais la perf en .net ce n'est pas quelque chose à regarder en 1er lieu
    d'abord parce que de nos jours les pcs sont puissants et que perdre 5 ns c'est pas bien grave
    et puis d'abord on fait un truc qui marche si possible bien découpé et après on regarde ce qu'on peut améliorer

    enfin au début faut pas s'inquiéter autant, il te faudrait plusieurs mois en intensif pour maitriser tout ce qui se trouve dans .net, donc c'est normal de réinventer des roues et de rater quelques concepts

    et si ton code est aussi aéré que tes posts ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre éprouvé
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 449
    Points : 991
    Points
    991
    Par défaut
    lol non c'est l'inverse pour le code, je commente méchamment et je découpe pas mal ce qui du coup me pose parfois des soucis avec les tutoriels, surtout avec les expressions lambdas, ou les imbriquées à gogo j'ai du mal à lire.

    Bon pour mon for j'ai trouvé en fait ma méthode qui inclus le for n'est plus asynchrone, c'est la fonction qui va appeler la tâche qui va être asynchrone ce qui du coup me permet de lance run thread par tâche, j'en ai ralenti un sur les trois pour vérifier et c'est ce que je voulais, je vais continuer par contre la lecture des pools de threads qui me parait incontournable.

    .Net est franchement super riche en effet, y'a pas mal de bon ceci dit, dans tout ça, c'est pour ça même que j'ai choisi au lieu de python. Après ça me parait normal de me casser les dents sur des concepts pareils, mais bon ça fait se creuser la tête et ça fait du bien ^^. Je comprends que ma question te stimule, mais dis toi que tu es une exception ce qui me parait fou car justement logiquement je me dis que les mecs les plus avancés doivent chercher à creuser pour optimiser.. refactoriser je crois que ça se nomme ? Après tu as raison, et c'est un mauvais réflexe que j'ai parfois du mal à perdre mais c'est aussi car je démarre à la bourre que je n'ai pas de formation.... alors j'ai cette angoisse de perdre mon temps dans un truc qui au final mènera à une impasse ou va ramer (et peut être que je devrais en effet pas m'en faire avec les pcs actuels) masi quand je vois certaines interfaces qui rament sur ma bécane alors que j'ai un bon i7 et 12 go de mémoire... je n'ai pas envie de faire pareil et je me dis que ça doit forcément arriver vite sinon ça se produirait pas. Enfin je crois. Bon après un jour j'ai foutu à genoux mon pc à l'époque en voulant créer un chrono en directX qui faisait je crois les nanos secondes... une lubie qui m'a calmé.

    Je me demandais en effet si au final passer par dynamic n'allait pas être plus long que de passer par reflection, entre autre, si ça valait le coup... mais c'est vrai que j'aurais peut être pas du me casser la tête. Ca part aussi du fait que je suis un gros flemmard qui préféère les fonctions polyvalentes plutot que de chaque fois réécrire à chaque fois que je dois lire en base de donnée, faire une recherche dans un fichier xml etc... alors qu'au final si je tapais tout le code peut être que ça serait mieux que de passer par ces méthodes polyvalents uqe je créè un jour faudra que je chronomètre d'ailleurs...


    Edit:
    J'ai lu deux fois le pool de threads c'était intéressant, ça m'a fait gamberger du coup que je pouvais faire une double boucle avec un pool de threads pour traiter X (tests de connexions serveurs) par Y threads. Après je suis étonné, qu'il n'existe pas directement une gestion avec une methode dédiée, il me semble de mémoire que c'est le cas pour les threads sur Python, mais j'ai pas eu à m'en servir pour le moment vu que ce sont des appels temporaires, mais d'avoir bossé sous c# ça m'a permis de me demander du coup s'il n'était pas plus judicieux au final de créer un thread avant les boucles que j'utilise plutot que d'en créer un à chaque boucle, faudra que je vérifie mon code.

    J'ai mis sur résolu, j'ai eu énormément de pistes et de réponses, et je vous remercie... Je reviendrais lire au c as ou la discussion se poursuive. Il m'est venu une question mais je la poserai ailleurs, c'était sur la communication entre threads, je me demandais s'il étaient réceptifs à l'abonnement aux signaux, mais je vérifierai par moi même.. pour le moment je me contente d'un flag.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 28/01/2012, 17h56
  2. Réponses: 3
    Dernier message: 13/07/2011, 15h21
  3. transmettre une variable d'une fenetre a une autre
    Par tix116 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 20/02/2009, 10h07
  4. insertion d'une fenetre dans une fenetre
    Par DeeVoiD dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 04/02/2009, 12h56
  5. Problème affichage d'une fenetre dans une fenetre
    Par zuzuu dans le forum Windows
    Réponses: 10
    Dernier message: 03/10/2007, 15h26

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