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 :

Problème backgroundWorker et interthread


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2009
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2009
    Messages : 18
    Par défaut Problème backgroundWorker et interthread
    Bonjour,

    J'ai un souci avec le backgroundworker, et je souhaite savoir si quelqu'un peut m'aider. mon application est composé d'un TabControl auquel est aloué dynamiquement un controle utilisateur.

    Quand je fonctionne en monothread, il n'y a pas de souci. Mais ceci demandant beaucoup de ressources et affectant un freeze de mon interface graphique, j'ai décidé de le mettre une partie du traitement dans le backgroundWorker.

    mon backgroudworker est créé dans la form principale. elle fait appel à une méthode qui va se charger d'alouer dynamiquement des controles utilisateur dans les TabPages correspondant.

    Tout ceci à l'air de fonctionner jusqu'au moment où je souhaite afficher le tour (dans la méthode du backgroundworker : RunWorkerCompleted). Je demande l'affichage via des méthodes. Et voici le message d'érreur qui j'ai à l'execution :

    Opération inter-threads non valide : le contrôle 'StatsTab' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Voici la partie du code du backgroundworker :

    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
     
     public void AddClient(AveragesData[][] Data)
            {
                //this.DelAllClientTabs();
     
                CurrentData = Data;
                ClientStat = new SimotionTab[Data.Length];            //create as many Simotion tab's group as number of client
                LoadForm = new Loading();
                backgroundWorker1.RunWorkerAsync();
     
            }
     
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                for (int Client = 0; Client < CurrentData.Length; Client++)
                {
                    ClientStat[Client] = new SimotionTab();
                    ClientStat[Client].Dock = DockStyle.Fill;
                    ClientStat[Client].BackColor = Color.LightGray;
                    ClientStat[Client].AddSimotionTab(CurrentData[Client]);
                }
            }
     
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                ClientTabControl = new TabControl();
     
                for (int Client = 0; Client < CurrentData.Length; Client++)
                {
                    this.ClientTabControl.TabPages.Add(CurrentData[Client][0].ClientName);
                    this.ClientTabControl.TabPages[Client].Controls.Add(ClientStat[Client]);
                }
                this.ClientTabControl.Dock = DockStyle.Fill;
                this.Controls.Add(ClientTabControl);
                this.QuickMenu.Visible = true;
     
                Sender.showClienttab();
     
            }
    La méthode qui affiche le tout dans l'interface principale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void showClienttab()
            {
                this.splitContainer1.Panel2.Controls.Add(clientTab1);
            }
    Pouvez-vous m'aider car je ne retrouve pas ce genre de problème sur google?

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 47
    Par défaut
    Il me semble qu'en .Net (au moins en winform) il n'y ait qu'un unique Thread qui maintienne l'UI en .Net (c'est une limitation).
    Utiliser le background worker pour paralléliser des opérations uniquement sur l'UI n'a donc pas de sens : en effet pour éviter les opérations inter-threads non valides, il faut utiliser la méthode Invoke(), qui va répercuter le travail sur le thread principal qui maintient l'UI (donc au final on n'a rien gagné).
    Bref la méthode DoWork() du background worker devrait surtout travailler sur des données , et les répercutions sur l'UI devraient plutôt être effectuées dans les méthodes ReportProgress() ou WorkerCompleted() qui s'exécutent dans le thread principal.
    Après il est toujours possible de placer des Invoke() dans le DoWork(), mais le background worker n'a d'intérêt que si le DoWork() fait autre chose que gérer l'affichage graphique.
    Plus de détails là car je ne suis pas forcément très clair : http://msdn.microsoft.com/en-us/library/ms171728.aspx

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2009
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2009
    Messages : 18
    Par défaut
    Le but de mon backgroundworker est de pouvoir mettre en forme une présentation de résultats pour être affiché ensuite. Pendant cette oppération qui est lourde, je voudrais éviter le freeze de ma form. Voilà pourquoi, je souhaite utiliser un thread.

  4. #4
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Bonjour,

    Comme dit par clenoir, tout ce qui est UI doit être fait dans le thread principal.
    Donc retourne sur ton premier code et essaye d'ajouter un SuspendLayout avant l'ajout des tabls et usercontrols puis un ResumeLayout juste après.

    Sinon je vois que tu as mis le new des SimotionTab (usercontrol) dans le DoWork est-ce ceci qui prend du temps ? Si oui, que fais-tu dans leur constructeur qui peut prendre du temps ?

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 47
    Par défaut
    Pendant cette oppération qui est lourde, je voudrais éviter le freeze de ma form.
    Eventuellement tu peux tenter d'utiliser des Thread.Sleep() dans ta boucle du DoWork(), et lancer donc ponctuellement tes mises à jour de l'UI (via un Invoke() ou backgroundWorker1.ReportProgress()). Si ça marche, ton composant risque de se charger de manière un peu aléatoire mais l'UI ne sera peut-être pas freezée.
    (sinon +1 pour l'utilisation des SuspendLayout())

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2009
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2009
    Messages : 18
    Par défaut
    Après analyse de ce qui se passe j'ai soupsonne que le problème vienne du fait que je créer des user control (SimotionTab et Statstabs) dans mon thread. Ces usercontrols, je souhaite les affichés.

    Mais le problème interviens quand mon thread à terminé sont boulot. le thread supprime les usercontrols qu'il a créé et donc appel la methode dispose qui donne ce genre de message :

    Opération inter-threads non valide : le contrôle 'StatsTab' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Y a il un moyen pour récupérer les usercontrols que le thread a créé dans mon programme pour pouvoir les afficher tranquillement?

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 198
    Par défaut
    pas lu, mais seul le thread qui a créé un controle peut le modifier, sachant qu'il convient de créer tous les controles sur le thread principal

    on peut utiliser des délégués pour revenir temporairement sur le thread principal puis retourner sur l'autre thread (this.invoke(le délégué))

    donc si dans ton thread tu ne veux faire que des manipulations de controles, il ne sert à rien
    par contre si tu fais du rapatriement de données ca peut être utile
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre averti
    Homme Profil pro
    Inscrit en
    Mai 2009
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2009
    Messages : 18
    Par défaut
    ok donc en fait ce que je veux faire est impossible.
    Merci à tous pour vos éclairages.

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. [Débutant] Problème backgroundworker et thread
    Par pepsi95 dans le forum VB.NET
    Réponses: 2
    Dernier message: 24/02/2012, 17h41
  3. Problème BackgroundWorker dans un MDI
    Par fragmonster dans le forum Windows Forms
    Réponses: 1
    Dernier message: 12/02/2009, 10h23
  4. Problème BackgroundWorker - WebBrowser - Delegate
    Par Anified dans le forum Windows Forms
    Réponses: 7
    Dernier message: 09/11/2007, 18h01
  5. [C# THREADS]problème avec backgroundworker
    Par sarapis dans le forum Windows Forms
    Réponses: 8
    Dernier message: 15/04/2007, 11h58

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