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

C# Discussion :

Utiliser des multiples backgroundworker


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Côte d'Ivoire

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

    Informations forums :
    Inscription : Janvier 2015
    Messages : 52
    Par défaut Utiliser des multiples backgroundworker
    Bonjour ,
    J'ai un winform appelé login qui demande un nom d'utilisateur et un mot de passe, vérifie les informations avec une base de données (en ligne) et affiche ensuite le winform principal, mais pour éviter que l'application ne se fige, j'ai utilisé deux backgroundworkers.
    Sur mon winform principal, j'ai plusieurs onglets pour changer de tableau.
    quand je clique sur mon bouton de connexion:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private  void btncon_Click(object sender, EventArgs e)
     {
        strLogin = tblogin.Text.Trim();
        pass = tbpwd.Text;
        if (!backgroundWorker1.IsBusy)
            backgroundWorker1.RunWorkerAsync();
     }
    et
    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 backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                string[] user = cm.login(strLogin, pass);
                int dataload = 0;
                if(user[0] != null)
                {
                   success = true;
                }
                else
                {
                    success = false;
                }
            }
    alors quand backgroundworker1 est fini, j'appelle backgroundWorker2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (success)
                {
                    backgroundWorker2.RunWorkerAsync();
                }
                else
                {
                    this.Show();
                }
            }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    main Principale; //main form
    private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
    {
      Principale = new main();
    }
     
        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
          this.Hide(); //hide login winform
          Principale.Show(); //show mainform
        }
    le soucis il y a certains bugs que je ne comprend pas du tout et c'est peut être de la manière dont j'utilise les backgroundworker avec mon gui

  2. #2
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Il n'y a aucune raison d'utiliser le second BackgroundWorker. Tu peux créer ta fenêtre principale simplement sur la fin de traitement du premier BackgroundWorker, si l'authentification a réussi. En plus de cela les composants graphiques ne peuvent être créés que sur le Thread de l'UI (celui qui gère à la base ta fenêtre de login).
    En outre, dans l'objet DoWorkEventArgs possède un propriété Result, de type object, à laquelle tu peux passer une valeur, par exemple le succès ou l'échec de la tentative de connexion, qui sera ensuite transmise à la procédure de fin de traitement par l'intermédiaire du paramètre RunWorkerCompletedEventArgs.
    Le BackgroundWorker sur la msdn : https://docs.microsoft.com/fr-fr/dot...ramework-4.7.2

  3. #3
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Côte d'Ivoire

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

    Informations forums :
    Inscription : Janvier 2015
    Messages : 52
    Par défaut
    la fenêtre principale charge aussi des données c'est pourquoi j'utilisais un deuxième backgroundworker.
    mais j'ai supprimé le deuxième backgroundworker comme tu l'as conseillé et pour créer la deuxieme fenêtre :

    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
    private main m;
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                model.Connexion cm = new model.Connexion();
                pass = Snippets.SHA1Util.SHA1HashStringForUTF8String(pass).ToString();
                string[] user = cm.login(strLogin, pass);
                if(user[0] != null)
                {
                        Int32.TryParse(user[0], out iduser);
                        Int32.TryParse(user[1], out idGrp);
                        Int32.TryParse(user[2], out idbtq);
                        nom = user[3];
                    if (idGrp != 3)
                    {
                        success = true;
                        m = new main();
                    }
                    else
                    {
                        success = false;
                    }
                }
                else
                {
                    success = false;
                }
            }
    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
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                pcLoader.Visible = false;
                if (success)
                {
                    pcLoader.Visible = false;
                    m.ShowDialog();
                }
                else
                {
                    tblogin.ReadOnly = false;
                    tbpwd.ReadOnly = false;
                    btncancel.Visible = false;
                    btncon.Visible = true;
                    MessageBox.Show("Veuillez contacter l'administrateur  \n Email ou mot de passe incorrect \n Ou votre accès n'est pas autorisé.");
                    this.Show();
                }
            }

  4. #4
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Dans cette situation tu peux avoir deux approches :
    - chargement des données dans la fenêtre de login, avant l'affichage de la fenêtre principale : dans le RunWorkerCompleted tu fais afficher dans ta fenêtre de login un message indiquant le chargement avant affichage de le fenêtre, puis tu appelles un second BackgroundWorker, avec affichage de la fenêtre principale à complétion du processus ;
    - chargement des données dans la fenêtre principale, que tu afficheras d'abord en mode (au moins partiellement) "verrouillé", c.à.d sans interaction avec la partie gérant les données, avec un BackgroundWorker appelé dans le chargement de la fenêtre ; à la fin de processus tu insères tes données dans la fenêtre et tu la déverrouilles.

    En gérant dans la fenêtre principale tu pourras envisager une gestion des erreurs, avec par exemple un bouton de retry et un éventuel message d'erreur si la récupération échoue (timeout, erreur serveur, perte du réseau, etc...). Si c'est une erreur d'authentification qui apparaît il faudra simplement fermer la fenêtre et ré-afficher la fenêtre de login.

  5. #5
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Côte d'Ivoire

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

    Informations forums :
    Inscription : Janvier 2015
    Messages : 52
    Par défaut
    mon backgroundworker ne fonctionne pas comme je veux , l'application continue de planter comme si il était inactif ,j'ai lue sur quelque part que c'est pas recommandé de manipuler le GUI dans le DoWork

  6. #6
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Il ne faut surtout pas manipuler la GUI dans le DoWork, c'est justement la méthode qui est exécutée sur le Thread en tâche de fond. Les manipulations de la GUI se font dans le ProgressChanged et le RunWorkerCompleted, qui s'exécutent sur le Thread d'origine (en principe celui de la GUI). Quelle manipulation de souhaites-tu faire dans le DoWork ?

  7. #7
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Côte d'Ivoire

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

    Informations forums :
    Inscription : Janvier 2015
    Messages : 52
    Par défaut
    problème resolu ,
    en premier je clique sur le bouton connexion du premier winForm :
    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
     
    private  void btncon_Click(object sender, EventArgs e)
            {
                username = tblogin.Text.Trim();
                pass = tbpwd.Text;
                if (String.IsNullOrWhiteSpace(username) || String.IsNullOrWhiteSpace(pass))
                {
                    MessageBox.Show("Veuillez remplir tous les champs SVP ");
                }
                else if(String.IsNullOrEmpty(username) || String.IsNullOrEmpty(pass)){
                    MessageBox.Show("Veuillez remplir tous les champs SVP ");
                }
                else
                {
                    if (!bgW1.IsBusy)
                    {
                        btncancel.Visible = true;
                        btncon.Visible = false;
                        tblogin.ReadOnly = true;
                        tbpwd.ReadOnly = true;
                        pcLoader.Visible = true;
                        bgW1.RunWorkerAsync();
                    }
                }
            }
    et voici mon DoWork :
    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
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
     
                string[] user = cm.login(username, pass); //retourne un array contenant les infos de l'utilisateur
                if(user[0] != null)
                {
                    Int32.TryParse(user[0], out iduser);
                    Int32.TryParse(user[1], out idGrp);
                    Int32.TryParse(user[2], out idbtq);
                    nom = user[3];
                    e.Result = (idGrp != 3) ?  true : false; 
                }
                else
                {
                    e.Result = false;
                }
            }
    et dans mon RunWorkerCompleted j'affiche le second winForm

    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
    private void bgW1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                pcLoader.Visible = false; //je masque le gif du loading
                bool resultat = (bool) e.Result;
                if (resultat) //si tout est okay 
                {
                    new principale().Show();
                    this.Hide(); //je cache le premier winform
                }
                else
                {
                    this.Show();
                    //si il y a des erreurs dans le login , je réactive le textbox du login , du mot de passe et je cache le bouton annuler
                    tblogin.ReadOnly = false; 
                    tbpwd.ReadOnly = false;
                    btncancel.Visible = false;
                    btncon.Visible = true;
                    MessageBox.Show("Veuillez contacter l'administrateur  \n Email ou mot de passe incorrect \n Ou votre accès n'est pas autorisé.");
                }
            }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private async void main_Load(object sender, EventArgs e)
            {
                await loadDgRapportGeneral();
                lbNameBtq.Text = db.single("SELECT nomBtq FROM boutiques WHERE idBtq =" + idBtq);
            }
    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
    private async Task loadDgRapportGeneral()
            {
                pcLoadingMain.Visible = true;
                await Task.Run(() => {
                    //[0] gain total ,[1] chiffre d'affaire ,[2] gain produit ,[3] depenses ,[4] canalsat ,[5] mois , annee
                    string[] datas = db.row(@"select (sum(gainproduit) + sum(canalsat) - sum(depenses)) as gain, sum(ca) as ca , sum(gainproduit) as gainproduit,  sum(depenses) as depensetotal, sum(canalsat) as totalcanalsat, monthname(dated) as mois , year(dated) as annee
                                                from ( (select v.dateVente as dated , v.idBtq as idBtq ,v.qteVendu*(v.prixVente - v.prixAchat) as gainproduit ,0 as canalsat, 0 as depenses , (v.qteVendu * v.prixVente) as ca   from ventes v) 
                                                union all
                                                (select d.dateDep as dated, d.idBtq as idBtq , 0 as gainproduit ,0 as canalsat, d.montant as depenses , 0 as ca   from depenses d)
                                                union all
                                                (select c.dateCanal as dated ,c.idBtq as idBtq , 0 as gainproduit , c.gain as canalsat, 0 as depenses , 0 as ca   from canal c)) x 
                                                where YEAR(CURRENT_DATE) = YEAR(dated) and MONTH(CURRENT_DATE) = MONTH(dated) and idBtq = " + principale.idBtq);
     
                    //[0] somme des prix unitaire d'achat , [1] sommes des prix unitaire de ventes
                    string[] datas2 = db.row("SELECT SUM(p.qDispProd * p.prixAprod) , SUM(p.qDispProd * p.prixVprod) FROM produits p WHERE  p.idBtq = " + idBtq);
                    //somme des prix unitaire d'achat
                    double PUA = Convert.ToInt32(datas2[0]);
                    lbSPUA.Text = PUA.ToString("#,0 CFA;-#,0 CFA");
                    //Somme des prix de vente unitaire
                    double PUV = Convert.ToInt32(datas2[1]);
                    lbSPUV.Text = PUV.ToString("#,0 CFA;-#,0 CFA");
     
                    //gain total
                    double resultat = Convert.ToInt32(datas[0]);
                    lbGainTotal.Text = resultat.ToString("#,0 CFA;-#,0 CFA");
     
                    //chiffre d'affaire
                    double CA = Convert.ToInt32(datas[1]);
                    lbCA.Text = CA.ToString("#,0 CFA;-#,0 CFA");
     
                    //gain produit
                    double gainP = Convert.ToInt32(datas[2]);
                    lbGainProduit.Text = gainP.ToString("#,0 CFA;-#,0 CFA");
                    //somme des depenses du mois
                    double depense = Convert.ToInt32(datas[3]);
                    lbDepense.Text = depense.ToString("#,0 CFA;-#,0 CFA");
     
                });
                pcLoadingMain.Visible = false; //je masque le loading sur le winForm de principale
            }

  8. #8
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    C'est normal que ça plante. Dans le dernier extrait de code la lambda passée en paramètre de Task.Run() est exécuté en tâche de fond ; or tu fais dedans des appels à la GUI. En principe cette fonction devrait juste récupérer les données et les renvoyer, puis laisser l'appelant (exécuté sur le Thread de L'UI) effectuer les affectations.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    private async Task loadDgRapportGeneral()
            {
                pcLoadingMain.Visible = true;
                var data = await Task.Run(() => { return dataService.FetchData(); }); // Ceci n'est pas un Task, mais un Task<T>, avec une propriété Result pour récupérer les données
                pcLoadingMain.Visible = true;
                }
    Ceci-dit j'ai quand même encore un doute, comme tu utilises déjà un await dans la méthode maint_Load. Le pattern async/await demande un peu de gymnastique intellectuelle, si le BackgroundWorker est plus clair pour toi tu peux rester sur ce modèle.

    Pour le temps de chargement long malgré tout, effectivement tu as une requête exécutée dans la méthode de chargement, tu devrais sans doute le faire dans en asynchrone aussi.

  9. #9
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Côte d'Ivoire

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

    Informations forums :
    Inscription : Janvier 2015
    Messages : 52
    Par défaut
    Oui merci pour l'astuce , j'ai pu faire fonctionner ça :

    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
    private async void main_Load(object sender, EventArgs e)
            {
                db = new Snippets.Db();
                pcLoadingMain.Visible = true;
                lbNameBtq.Text = await loadNameBtq();
                var tuples = await loadDgRapportGeneral();
                //tuples 1
                lbGainTotal.Text      = tuples.Item1[0].ToString();
                lbCA.Text             = tuples.Item1[1].ToString();
                lbGainProduit.Text    = tuples.Item1[2].ToString();
                lbDepense.Text        = tuples.Item1[3].ToString();
                lbCanal.Text          = tuples.Item1[4].ToString();
                //tuples2
                lbSPUA.Text = tuples.Item2[0].ToString();
                lbSPUV.Text = tuples.Item2[1].ToString();
                pcLoadingMain.Visible = false;
            }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private async Task<string> loadNameBtq()
            {
                string value = string.Empty;
                await Task.Run(() =>
                {
                   value = db.single("SELECT nomBtq FROM boutiques WHERE idBtq =" + idBtq);
                });
                return value;
            }
    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
     private async Task<Tuple<string[],string[],string>> loadDgRapportGeneral()
            {
     
                string[] datas = new string[6];
                string[] datas2 = new string[6];
                string nbVente = string.Empty;
     
                await Task.Run(() => {
                     datas = db.row(@"select (sum(gainproduit) + sum(canalsat) - sum(depenses)) as gain, sum(ca) as ca , sum(gainproduit) as gainproduit,  sum(depenses) as depensetotal, sum(canalsat) as totalcanalsat, monthname(dated) as mois , year(dated) as annee
                                                from ( (select v.dateVente as dated , v.idBtq as idBtq ,v.qteVendu*(v.prixVente - v.prixAchat) as gainproduit ,0 as canalsat, 0 as depenses , (v.qteVendu * v.prixVente) as ca   from ventes v) 
                                                union all
                                                (select d.dateDep as dated, d.idBtq as idBtq , 0 as gainproduit ,0 as canalsat, d.montant as depenses , 0 as ca   from depenses d)
                                                union all
                                                (select c.dateCanal as dated ,c.idBtq as idBtq , 0 as gainproduit , c.gain as canalsat, 0 as depenses , 0 as ca   from canal c)) x 
                                                where YEAR(CURRENT_DATE) = YEAR(dated) and MONTH(CURRENT_DATE) = MONTH(dated) and idBtq = " + principale.idBtq);
     
    nbVente = db.single("SELECT SUM(qteVendu) FROM ventes  WHERE MONTH(dateVente) = MONTH(CURRENT_DATE()) AND YEAR(dateVente) = YEAR(CURRENT_DATE()) AND idBtq =" + principale.idBtq);
     
                    datas2 = db.row("SELECT SUM(p.qDispProd * p.prixAprod) , SUM(p.qDispProd * p.prixVprod) FROM produits p WHERE  p.idBtq = " + idBtq);
     
                });        
                return new Tuple<string[],string[], string>(datas,datas2,nbVente);
            }

Discussions similaires

  1. regexp utilisant des multiples
    Par jige23 dans le forum Access
    Réponses: 2
    Dernier message: 03/03/2015, 10h08
  2. Utiliser des connexions multiples sur des listes
    Par MasterJul dans le forum SharePoint
    Réponses: 0
    Dernier message: 08/02/2008, 12h41
  3. [MySQL] Utilisation des valeur choix multiple pour executer une requete une valeur a la fois
    Par guigui69 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 26/12/2007, 16h43
  4. Utilisation des choix d'une zdl à choix multiples pour une requête
    Par Nanouche dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 10/10/2007, 02h57
  5. Utilisation des liste à choix multiples
    Par mic79 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 04/07/2005, 11h40

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