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 :

backgroundworker et progressbar


Sujet :

C#

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 17
    Points : 14
    Points
    14
    Par défaut backgroundworker et progressbar
    Bonjour.

    Je développe actuellement une application afin de m'aider dans mes tâches quotidiennes, et je rencontre un soucis concernant les progressbar en conjonction avec un backgroundworker.
    Mon interface est faite en WPF.

    Pour faciliter, voilà ce dont je dispose : une classe contenant les différentes actions des boutons (le main thread), ainsi que d'une autre classe contenant mes requêtes wmi.

    Donc, voilà ce que j'essaie de faire.
    Code de la main window, avec les actions des boutons :

    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
     
    namespace MyApp
    {
        public partial class MainWindow : MetroWindow
        {
            BackgroundWorker bgw = new BackgroundWorker();
     
            public MainWindow()
            {
                InitializeComponent();
            }
     
            private void BtnProcesse_Click(object sender, RoutedEventArgs e)
            {
                String hostname = tb_hostname.Text;
     
                bgw.DoWork += new DoWorkEventHandler(Wmi_Requests.getProcesses(hostname)); // Ne fonctionne pas
                bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
                bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
                bgw.WorkerReportsProgress = true;
                bgw.RunWorkerAsync(hostname);
            }
     
            void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
                // Job à effectuer
            }
     
            void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                Progressbar1.Value = e.ProgressPercentage;
            }
     
            void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                // Terminé
            }
        }
    }
    Et la classe contenant mes requêtes wmi ressemble a ceci :

    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
     
    class Wmi_Requests
        {
            private readonly MainWindow Form;
     
            public Wmi_Requests(MainWindow Form)
            {
                this.Form = Form;
            }
     
            public void getProcesses(string hostname)
            {
     
                ManagementScope scope = new ManagementScope("\\\\" + hostname + "\\root\\cimv2");
                scope.Connect();
     
                ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
     
                foreach (ManagementObject product in searcher.Get())
                {
                    // Pour cet exemple, sortie vers la console
                    Object Name = product["Name"].ToString();
                    Object Version = product["ProcessId"].ToString();
     
                    Console.WriteLine(Name + " --- " + Version);
                }
            }
        }
    }
    Donc pour résumer, lorsque j'appuie sur le bouton "btn_processe", ça call la méthode "getProcesses" de la class "Wmi_Requests". Etant donné que certaines requêtes peuvent être longues, et afin de ne pas freezer l'interface, j'ai opté pour les background worker + progressbar pour avoir un état d'avancement. Mais je n'y arrive pas :'(

    Enfin, il faut tenir compte du fait que biensur je n'aurai pas qu'un seul bouton, et que plusieurs actions seront possible. Après je ne sais pas si dans ce cas, il est mieux d'instancier des nouveaux backgroundworker, ou d'utiliser le même, avec le job différent...

    J'espère avoir été clair. Si quelqu'un pourrai m'aiguiller, si possible, avec un exemple, car je ne maitrise pas trop les backgroundworker.

  2. #2
    Membre confirmé
    Avatar de nouanda
    Homme Profil pro
    Hobbyist
    Inscrit en
    Mai 2002
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Australie

    Informations professionnelles :
    Activité : Hobbyist

    Informations forums :
    Inscription : Mai 2002
    Messages : 246
    Points : 627
    Points
    627
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bgw.DoWork += new DoWorkEventHandler(Wmi_Requests.getProcesses(hostname)); // Ne fonctionne pas
    remplace cela par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
                Wmi_Requests.getProcesses(hostname);
            }
    Ensuite, le progress ne marche que si tu dis au bgw que le progress a change...
    il faut ecrire quelque part [c]ReportProgress(la valeur de progress)[\c]
    Le seul endroit pour le faire, c'est dans la méthode getProcesses.
    par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
                var productcollection= searcher.Get();
                int i= 0;
                foreach (ManagementObject product in productcollection)
                {
                    // Pour cet exemple, sortie vers la console
                    Object Name = product["Name"].ToString();
                    Object Version = product["ProcessId"].ToString();
     
                    Console.WriteLine(Name + " --- " + Version);
                    i++;
                    bgw.ReportProgress(i/productcollection.Count*100);
                }
    Tu vas aussi avoir un problème avec les events ajoutes par [c]+= new[\c]. A chaque fois que l'utilisateur va cliquer sur le bouton, tu souscris aux événements une fois de plus. 1 clic=1 souscription a l’événement. 2 clics = 2 souscriptions a l’événement...
    Donc après n clic, chaque événement va se lancer n fois... pas forcement idéal... (piège classique pour les débutants, je me suis fait déjà avoir, et je ne suis certainement pas le seul!)

    Enfin, pour la dernière question, je dirai un background worker par bouton, sous réserve que tu gères l'annulation des taches (WorkerSupportsCancellation = true)

    La documentation est très claire, n'oublie pas de t'y référer.


    EDIT: il va aussi falloir que tu vérifies la portée de tes méthodes. getProcesses n'est pas static, ça va planter... mais VS devrait te le dire!

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 17
    Points : 14
    Points
    14
    Par défaut
    Merci beaucoup pour ta réponse claire.

    La méthode est bien "static", j'ai du faire un mauvais copier/coller vers le forum

    il faut ecrire quelque part [c]ReportProgress(la valeur de progress)[\c]
    Le seul endroit pour le faire, c'est dans la méthode getProcesses.
    C'est le point que je ne comprend pas. Car depuis la methode getProcesses, je n'accède pas au worker qui est initié depuis l'autre classe. (a moins que j'ai mal compris ce que tu voulais dire)

    Quoiqu'il en soit, je vas essayer de modifier ça en tenant compte de tes remarques et du lien que tu m'a fourni.

    EDIT : Et j'ai oublié de te demandé, comment palier au soucis de souscription aux events "+=new" ? Effectivement, je n'y avais pas pensé

  4. #4
    Membre confirmé
    Avatar de nouanda
    Homme Profil pro
    Hobbyist
    Inscrit en
    Mai 2002
    Messages
    246
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Australie

    Informations professionnelles :
    Activité : Hobbyist

    Informations forums :
    Inscription : Mai 2002
    Messages : 246
    Points : 627
    Points
    627
    Par défaut
    depuis la methode getProcesses, je n'accède pas au worker qui est initié depuis l'autre classe. (a moins que j'ai mal compris ce que tu voulais dire)
    Tu as bien compris. Une methode quick and dirty serait de passer le backgourndworker en argument optionnel de la methode getProcess
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void getProcesses(string hostname, BackgroundWorker callerbgw = null)
            {
            //blabla
     
            if (callerbgw != null && callerbgw.WorkerReportsProgress)
           {
                   callerbgw.ReportProgress(i/productcollection.Count*100);
            }
    }
    Pour les evenements, si tu pars sur un schema 1 bouton = 1 background worker, le plus simple est de les assigner une fois pour toute, au lancement de l'application.
    Si tu veux recycler tes bgw, il faudra faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bgw.Evenement -= AncienEventHandler;
    bgw.Evenement += NouvelEventHandler;

Discussions similaires

  1. [Débutant] Problème backgroundWorker et progressBar
    Par AlphaMoody dans le forum Windows Forms
    Réponses: 1
    Dernier message: 27/06/2012, 14h30
  2. backgroundworker avec plusieurs progressbar
    Par tortuegenie dans le forum Windows Forms
    Réponses: 1
    Dernier message: 01/06/2011, 16h54
  3. backgroundworker et progressBar
    Par gharras dans le forum C#
    Réponses: 8
    Dernier message: 30/11/2009, 12h23
  4. Réponses: 4
    Dernier message: 24/07/2007, 10h57
  5. Couleur de ProgressBar
    Par benj63 dans le forum C++Builder
    Réponses: 7
    Dernier message: 04/07/2002, 17h33

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