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

Windows Forms Discussion :

le programme "ne répond pas" durant un temps de calcul long


Sujet :

Windows Forms

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 57
    Points : 42
    Points
    42
    Par défaut le programme "ne répond pas" durant un temps de calcul long
    bonjour,

    j'ai réussi a faire le petit programme de calcul que je voulais, il fait ce que je lui demande, nikel, mais quand je pousse un peu sur le nombre de claculs, il ne répond pas jusqu'a la fin de l'éxécution. J'ai mis une progress bar histoire de savoir ou s'en est durant les longs calculs, mais du coup ça sert a rien :/
    je voulais juste savoir si c'était normal, si ça voulais dire que c'était codé avec les pieds ou autres choses que je ne soupçonne pas.

    merci

  2. #2
    Membre chevronné
    Avatar de PixelJuice
    Homme Profil pro
    Ingénieur .NET & Game Designer
    Inscrit en
    Janvier 2014
    Messages
    639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur .NET & Game Designer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2014
    Messages : 639
    Points : 2 148
    Points
    2 148
    Par défaut
    Bonjour,

    il est possible que ton calcul puisse être optimisé (il nous faudrait donc ta méthode de calcul )par contre , si le calcul est trop long quoi qu'il arrive , il te faudra le faire a l'aide d'un thread.

    Si le programme ne réponds c'est que , ton calcul monopolise toute l'attention du thread principale , celui qui est aussi responsable de l'interface du logiciel , du coup il n'a plus le temps de s'occuper du programme lui même et freeze.

    Tu peux aussi utiliser un BackgroundWorker , qui est un composant .NET qui permet de simplifier l'utilisation d'un Thread.

  3. #3
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Solution "Quick and dirty" : faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Applications.DoEvents() ;
    Après chaque mise à jour de la ProgressBar.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  4. #4
    Rédacteur
    Avatar de The_badger_man
    Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2005
    Messages
    2 745
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 745
    Points : 8 538
    Points
    8 538
    Les règles du forum
    Le trio magique : FAQ + Cours + fonction rechercher
    Mes articles
    Pas de questions par messages privés svp

    Software is never finished, only abandoned.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 57
    Points : 42
    Points
    42
    Par défaut
    merci pour vos réponses, je vais voir, je comptais essayer le multithreading donc vais déja voir pour un thread et si c'est trop compliqué je vais opter pour le background worker

    voici mes boucles qui font varier les paramètres de mon calcul :
    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
     for (double x = dxmin; x <= dxmax; x++)
                    {
                        for (y = dymin; y <= dymax; y++)
                        {
                            for (double z = zmin; z <= zmax; z++)
                            {
                                for (double h = hmin; h <= hmax; h++)
                                {
                                    for (double g = gmin; g <= gmax + 0.0001; g += 0.100000000000)
                                    {
                                        prism[m, 0] = x;
                                        prism[m, 1] = y;
                                        prism[m, 2] = z;
                                        prism[m, 3] = h;
                                        prism[m, 4] = g;
                                        RMS = 0;
                                        Grav.CalculAnomalie(x, y, z, g, h, X, centre, Y, TailleMaille, maille, R, DG, anomalie);
                                        for (int i = 0; i < TailleMaille; i++)
                                        {
                                            RMS += Math.Sqrt(Math.Pow((G[i] - anomalie[i]), 2) /TailleMaille);//Math.Pow((G[i] - anomalie[i]), 2) / (G.Max() - G.Min())
                                        }
     
                                        prism[m, 5] = RMS; //ajoute la RMS en colonne 6 
                                        Trms[m] = RMS;
                                        progressBar1.Value = m;
                                        m = m + 1;
                                    }
                                }
                            }
                        }
                    }
    et voici le détail de ma class Grav :
    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 class Grav
    {
        static public double[] CalculAnomalie(double x, double y, double z, double g, double h, double [] X, double centre, double [] Y, int TailleMaille, double[,] maille, double[,] R, double[,] DG, double[] anomalie)
        {
            double x1 = X[(int)centre] - x / 2;
            //Console.WriteLine(x1);
            double y1 = Y[(int)centre] + y / 2;
            double z1 = z + 0.0000001;
            double Dg = g;
            double x2 = X[(int)centre] + x / 2;
            double y2 = Y[(int)centre] - y / 2;
            double z2 = z1 + h;
     
     
            //calcul des dx, dy, dz 
     
            for (int i = 0; i < TailleMaille; i++)
            {
                //Console.WriteLine(maille.GetLength(1));
                maille[i, 4] = x1 - maille[i, 0]; //dx1
                maille[i, 5] = x2 - maille[i, 0]; //dx2
                maille[i, 6] = y1 - maille[i, 1]; //dy1
                maille[i, 7] = y2 - maille[i, 1]; //dy2
                maille[i, 8] = z2 - maille[i, 2]; //dz1
                maille[i, 9] = z1 - maille[i, 2]; //dz2
            }
     
     
            //calcul de la distance du point a tous les bords du prisme
     
            for (int i = 0; i < TailleMaille; i++)
            {
                R[i, 0] = Math.Sqrt(Math.Pow(maille[i, 4], 2) + Math.Pow(maille[i, 6], 2) + Math.Pow(maille[i, 8], 2));
                R[i, 1] = Math.Sqrt(Math.Pow(maille[i, 4], 2) + Math.Pow(maille[i, 6], 2) + Math.Pow(maille[i, 9], 2));
                R[i, 2] = Math.Sqrt(Math.Pow(maille[i, 5], 2) + Math.Pow(maille[i, 6], 2) + Math.Pow(maille[i, 8], 2));
                R[i, 3] = Math.Sqrt(Math.Pow(maille[i, 5], 2) + Math.Pow(maille[i, 6], 2) + Math.Pow(maille[i, 9], 2));
                R[i, 4] = Math.Sqrt(Math.Pow(maille[i, 5], 2) + Math.Pow(maille[i, 7], 2) + Math.Pow(maille[i, 8], 2));
                R[i, 5] = Math.Sqrt(Math.Pow(maille[i, 5], 2) + Math.Pow(maille[i, 7], 2) + Math.Pow(maille[i, 9], 2));
                R[i, 6] = Math.Sqrt(Math.Pow(maille[i, 4], 2) + Math.Pow(maille[i, 7], 2) + Math.Pow(maille[i, 8], 2));
                R[i, 7] = Math.Sqrt(Math.Pow(maille[i, 4], 2) + Math.Pow(maille[i, 7], 2) + Math.Pow(maille[i, 9], 2));
            }
     
            //Calcul des anomalies liees aux differents bords
            for (int i = 0; i < TailleMaille; i++)
            {
                DG[i, 0] = -0.00667 * Dg * 1000 * (maille[i, 8] * Math.Atan(maille[i, 4] * maille[i, 6] / (maille[i, 8] * R[i, 0])) - maille[i, 4] * Math.Log(R[i, 0] + maille[i, 6]) - maille[i, 6] * Math.Log(R[i, 0] + maille[i, 4]));
                DG[i, 1] = 0.00667 * Dg * 1000 * (maille[i, 9] * Math.Atan(maille[i, 4] * maille[i, 6] / (maille[i, 9] * R[i, 1])) - maille[i, 4] * Math.Log(R[i, 1] + maille[i, 6]) - maille[i, 6] * Math.Log(R[i, 1] + maille[i, 4]));
                DG[i, 2] = 0.00667 * Dg * 1000 * (maille[i, 8] * Math.Atan(maille[i, 5] * maille[i, 6] / (maille[i, 8] * R[i, 2])) - maille[i, 5] * Math.Log(R[i, 2] + maille[i, 6]) - maille[i, 6] * Math.Log(R[i, 2] + maille[i, 5]));
                DG[i, 3] = -0.00667 * Dg * 1000 * (maille[i, 9] * Math.Atan(maille[i, 5] * maille[i, 6] / (maille[i, 9] * R[i, 3])) - maille[i, 5] * Math.Log(R[i, 3] + maille[i, 6]) - maille[i, 6] * Math.Log(R[i, 3] + maille[i, 5]));
                DG[i, 4] = -0.00667 * Dg * 1000 * (maille[i, 8] * Math.Atan(maille[i, 5] * maille[i, 7] / (maille[i, 8] * R[i, 4])) - maille[i, 5] * Math.Log(R[i, 4] + maille[i, 7]) - maille[i, 7] * Math.Log(R[i, 4] + maille[i, 5]));
                DG[i, 5] = 0.00667 * Dg * 1000 * (maille[i, 9] * Math.Atan(maille[i, 5] * maille[i, 7] / (maille[i, 9] * R[i, 5])) - maille[i, 5] * Math.Log(R[i, 5] + maille[i, 7]) - maille[i, 7] * Math.Log(R[i, 5] + maille[i, 5]));
                DG[i, 6] = 0.00667 * Dg * 1000 * (maille[i, 8] * Math.Atan(maille[i, 4] * maille[i, 7] / (maille[i, 8] * R[i, 6])) - maille[i, 4] * Math.Log(R[i, 6] + maille[i, 7]) - maille[i, 7] * Math.Log(R[i, 6] + maille[i, 4]));
                DG[i, 7] = -0.00667 * Dg * 1000 * (maille[i, 9] * Math.Atan(maille[i, 4] * maille[i, 7] / (maille[i, 9] * R[i, 7])) - maille[i, 4] * Math.Log(R[i, 7] + maille[i, 7]) - maille[i, 7] * Math.Log(R[i, 7] + maille[i, 4]));
            }
            //somme des DG
            for (int i = 0; i < TailleMaille; i++)
            {
                anomalie[i] = DG[i, 0] + DG[i, 1] + DG[i, 2] + DG[i, 3] + DG[i, 4] + DG[i, 5] + DG[i, 6] + DG[i, 7];
     
            }
            return anomalie;
        }
    }
    j'ai surement de mauvais habitudes en terme de nomenclature etc ... du coup ça risque d'etre un peu imbitable :/

  6. #6
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 931
    Points : 1 975
    Points
    1 975
    Par défaut
    Bonjour

    Dans cette discussion
    http://www.developpez.net/forums/d14...kgroundworker/
    Ph_Gr m'a suggéré que le backgroundworker était devenu "has been ", avec l'arrivée de async/await dans le framework 4.5.

    Pour avoir découvert le backgroundworker il y a quelques mois et le async/Await il y a quelques jours, je confirme que le async/await est d'une simplicité remarquable ! Il y a une notion de "tache" retournées par les fonction pas évidente à comprendre mais une fois compris c'est bien plus simple à coder et à relire ensuite.

    Si jamais...
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  7. #7
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Je rejoins les autres sur l'obligation d'utiliser un thread pour vraiment résoudre le problème, et notamment l'utilisation de async/await plutôt que le BackgroundWorker. Quoique un bête Application.DoEvents marcherait très bien ici.

    Cela dit, il y a de la marge pour optimiser si ça t'intéresse :
    * Remplace Math.Pow(x, 2) par x*x et simplifie aussi ta ligne "RMS += " pour virer le Math.Pow et le Math.Sqrt (sqrt(TailleMaille) peut être pré-calculé)

    * Introduis une structure Vecteur, cela simplifiera ton code, cela supprimera des vérifications aux indices, et en réduisant la dimension de tes tableaux le framework pourra encore en supprimer davantage.

    * Il semble que tu peux supprimer plusieurs tableaux pour les remplacer chacun par quelques bêtes variables, cela ferait gagner beaucoup de temps. Vire donc R, DG, anomalie et n'écrit pas dans maille, contente-toi de lire. En prime ça rendra ton code plus clair.

    * Faire ce genre de choses sur le CPU plutôt que sur le GPU en 2014 c'est un appel au crime !
    Il y aurait moyen de rendre ton truc 50 fois plus rapide et ce n'est pas compliqué (cherche "opencl dotnet"). Si ça te fait peur essaie au moins de paralléliser avec un Parallel.For. Dans les deux cas la seule difficulté est de simplifier ton algo pour qu'il n'y ait pas d'écritures concurrentes dans les mêmes cases mémoires, d'où à nouveau l'intérêt de virer des tableaux.

    Le seule obstacle pour paralléliser c'est l'incrémentation de m à la fin. Tu peux soit calculer m directement en fonction des coordonnées, soit pour le CPU utiliser Interlocked.Increment en déclarant m comme "volatile".


    Si tu fais tout ce que j'ai dit je pense que tu auras au moins un gain d'un facteur de 100, peut-être bien plus.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 26
    Points : 89
    Points
    89
    Par défaut
    Hello eweca,

    J'ai posté ici http://www.developpez.net/forums/d14...e/#post7754089 un modèle d'algo qui utilise Task pour lancer un thread en background, et l'objet Progress pour rafraichir la barre de progression.
    Tu peux utiliser exactement la même technique.

    L'utilisation de Application.DoEvents() est à proscrire, surtout si tu veux éviter de stopper ton aglo pour mettre à jour l'IHM !

Discussions similaires

  1. Programme MicrosoftOutlook ne répond pas
    Par x4c5rt dans le forum Windows 7
    Réponses: 4
    Dernier message: 23/11/2010, 09h28
  2. Mon sous-programme ne répond pas lors de l'appel
    Par Stagiette dans le forum C#
    Réponses: 3
    Dernier message: 28/01/2010, 10h21

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