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 :

Thread, opérations longues et progressbar


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de thelpi
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 217
    Par défaut Thread, opérations longues et progressbar
    Bonjour à tous,

    J'ai une appli en WPF 3.5 qui, avant de lancer sa fenêtre principale, doit effectuer certaines vérifications de pré-requis. Certaines des ces opérations peuvent être longues (plusieurs minutes) donc je me suis dit : thread parallèle + fenêtre affichant une barre de progression indéterminée.

    J'ai tenté cela par 2 codes différents, les 2 ne sont pas du tout satisfaisants:

    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
     
        /// <summary>
        /// classe gérant les appels au thread d'opérations longues
        /// </summary>
        public class ThreadManager
        {
            private static ThreadManager _instance = null;
            public static ThreadManager Instance
            {
                get
                {
                    if (_instance == null)
                        _instance = new ThreadManager();
                    return _instance;
                }
            }
     
            /// <summary>
            /// démarre le thread parallèle
            /// </summary>
            /// <param name="_callBack">méthode lancé par le thread</param>
            /// <param name="_actionName">intitulé de l'action</param>
            public void Launch(ThreadStart _callBack, string _actionName)
            {
                Thread th = new Thread(_callBack);
                th.IsBackground = true;
                th.Start();
                wdwWait frmWait = new wdwWait(_actionName);
                frmWait.Show();
                th.Join();
                frmWait.Close();
            }
        }
    avec cette méthode, j'ai un gros carré blanc à la place de ma fenêtre wdwWait, avec un sablier et un fameux message "ne répond pas", en attedant la fin de de th.Join()...

    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
     
    /// <summary>
        /// classe gérant les appels au thread d'opérations longues
        /// </summary>
        public class ThreadManager
        {
            private static ThreadManager _instance = null;
            public static ThreadManager Instance
            {
                get
                {
                    if (_instance == null)
                        _instance = new ThreadManager();
                    return _instance;
                }
            }
     
            private System.Timers.Timer t;
            private wdwWait frmWait;
            private Thread th;
     
            /// <summary>
            /// démarre le thread parallèle
            /// </summary>
            /// <param name="_callBack">méthode lancé par le thread</param>
            /// <param name="_actionName">intitulé de l'action</param>
            public void Launch(ThreadStart _callBack, string _actionName)
            {
                th = new Thread(_callBack);
                th.IsBackground = true;
                th.Start();
     
                t = new System.Timers.Timer(500);
                t.Enabled = true;
                t.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerTick);
     
                frmWait = new wdwWait(_actionName);
                frmWait.ShowDialog();
            }
     
            public void OnTimerTick(object o, System.Timers.ElapsedEventArgs e)
            {
                if (!th.IsAlive)
                    frmWait.Close();
            }
        }
    Avec cette option la, la fenêtre d'attente réagit bien, mais j'ai belle exception m'empêchant de fermer ma fenêtre à la fin du thread ("Le thread appelant ne peut pas accéder à cet objet parce qu'un autre thread en est propriétaire.")

    Je suis bien bloqué là, merci pour toute aide

  2. #2
    Membre averti
    Inscrit en
    Août 2006
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 34
    Par défaut
    salut,
    dans ton deuxième code essaie de faire un Abort du thread avant de fermer la Form

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public void OnTimerTick(object o, System.Timers.ElapsedEventArgs e)
            {
                if (!th.IsAlive)
                   {
                    th.Abort()
                    frmWait.Close();
                    }
            }

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    En WPF (comme en WinForms d'ailleurs), on ne peut accéder à l'interface graphique qu'à partir du thread qui l'a créée. Si un autre thread doit effectuer une opération sur l'interface graphique, il faut passer par le Dispatcher de l'interface (méthode Dispatcher.Invoke).

    Ta première méthode avec le Join n'est pas adaptée puisqu'elle bloque le thread principal (qui met à jour l'interface graphique) jusqu'à la fin du thread de traitement : tu perds tout l'intérêt de faire le traitement dans un autre thread.

    Ta 2e méthode pourrait marcher mais tu n'utilises pas le bon type de timer : System.Timers.Timer lève l'évènement Elapsed sur un thread du ThreadPool, et non sur celui de l'interface, d'où l'erreur quand tu essaies de fermer la fenêtre. Il faudrait plutôt utiliser un System.Windows.Threading.DispatcherTimer (spécifique à WPF).

    Une autre solution, plus simple et plus propre à mon avis, serait d'utiliser un BackgroundWorker pour effectuer le traitement : ce composant effectue le traitement sur un autre thread, mais déclenche les évènements ProgressChanged et RunWorkerCompleted sur le thread qui a créé le BackgroundWorker (en général le thread d'interface).

  4. #4
    Membre confirmé Avatar de thelpi
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 217
    Par défaut
    Merci infiniment !!! ça marche très bien avec la solution du DispatcherTimer. J'avais regardé la solution du BackGroundWorker mais j'avais pas bien saisi le fonctionnement (notamment à quel niveau on lui donne la méthode à exécuter).

    J'avais une dernière question cependant : en windows form, on peut sans problème faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    maForm.Invoke(monDélégué)
    en WPF, je ne trouve aucune méthode concernant Invoke... Normal?

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par thelpi Voir le message
    J'avais regardé la solution du BackGroundWorker mais j'avais pas bien saisi le fonctionnement (notamment à quel niveau on lui donne la méthode à exécuter).
    Il suffit d'affecter un handler à l'évènement DoWork, dans lequel tu fais le traitement.

    Citation Envoyé par thelpi Voir le message
    J'avais une dernière question cependant : en windows form, on peut sans problème faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    maForm.Invoke(monDélégué)
    en WPF, je ne trouve aucune méthode concernant Invoke... Normal?
    On n'appelle pas directement Invoke sur le contrôle, mais sur la propriété Dispatcher du contrôle.

  6. #6
    Membre confirmé Avatar de thelpi
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 217
    Par défaut
    Ok, merci pour toutes ces précisions.
    @plus

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 24/11/2006, 22h30
  2. [vb2005]Progressbar et thread
    Par stargates dans le forum Windows Forms
    Réponses: 2
    Dernier message: 04/06/2006, 07h38
  3. Opération mathématique entre deux Threads
    Par rvzip64 dans le forum Langage
    Réponses: 11
    Dernier message: 13/06/2005, 11h58
  4. Réponses: 5
    Dernier message: 10/05/2005, 10h22
  5. [MFC] dialog & thread & progressbar
    Par Tigris94 dans le forum MFC
    Réponses: 4
    Dernier message: 05/04/2005, 15h51

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