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 :

arret et reprise d'un thread


Sujet :

Windows Forms

  1. #1
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 182
    Par défaut arret et reprise d'un thread
    Bonjour,

    je suis confronté à un probleme que je n'arrive pas à resoudre.
    Je lance un thread qui fais un long traitement qui crée des fichiers et ecrit dedans.
    J'arrete le thread en appelant dessus la methode abort(), pas de probleme le thread s'arrete.
    Le probleme se pose lorsque je relance le thread, j'ai alors une IO exception, qui me dis que le fichier est utilisé par un autre process.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // demarrage et relance du thread
    PgbThread = new Thread(new ThreadStart(Treatment));
                    PgbThread.IsBackground = true;
                    PgbThread.Start();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // arret du thread
     PgbThread.Abort();

  2. #2
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    C'est normal...

    Si tu ouvres le fichier dans ton thread de traitement, Windows ( l'OS) te
    reserve un handle de fichier et lors du abort sur ton thread, si tu n'as pas
    "fermer" correctement ton fichier (File.Close par exemple) , l'application
    va garder le handle sur le fichier et tu auras du mal à écrire dedans par la suite

    donc, en regle general, faire un abort sur un thread nécéssite que le thread
    se "ferme" correctement si possible

    The Monz, toulouse

  3. #3
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 182
    Par défaut
    Citation Envoyé par theMonz31
    donc, en regle general, faire un abort sur un thread nécéssite que le thread
    se "ferme" correctement si possible

    The Monz, toulouse
    c'est a dire ?

  4. #4
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    C'est à dire que ton fichier il est encore ouvert.
    Donc forcément, tu peux pas bosser dessus paske t'as killé ton thread comme un gros crado

    "Mais comment on fait alors ?"
    Plutôt que de tuer salement un mec qui fait bien gentiment son travail, il suffit dans la boucle principal de ton thread de lui coller un boolean "continuer".
    Tant que le boolean est vrai, alors ton thread bosse.
    Quand tu mets le booléen à faux, ton thread sais qu'il doit s'arrêter, et là il exécutera le Close() qui va bien pour fermer ton fichier.

  5. #5
    Membre confirmé Avatar de dragohn
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Août 2006
    Messages : 85
    Par défaut
    Bonjour,

    vaut il mieux utiliser votre solution Mose, ou passer par un bloc try/catch/finally et capturer l'exception ThreadAbortException pour fermer le fichier/finir le traitement.
    Ma question peut sembler de novice (je le suis), et je dois admettre que j'avais pensé à traiter ça que via l'exception... à faire ou éviter?

  6. #6
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 182
    Par défaut
    Citation Envoyé par Mose
    C'est à dire que ton fichier il est encore ouvert.
    Donc forcément, tu peux pas bosser dessus paske t'as killé ton thread comme un gros crado

    "Mais comment on fait alors ?"
    Plutôt que de tuer salement un mec qui fait bien gentiment son travail, il suffit dans la boucle principal de ton thread de lui coller un boolean "continuer".
    Tant que le boolean est vrai, alors ton thread bosse.
    Quand tu mets le booléen à faux, ton thread sais qu'il doit s'arrêter, et là il exécutera le Close() qui va bien pour fermer ton fichier.
    j'ai essayé cette technique mais le probleme est que le thread est arreté à la premiere rentrée dans la boucle, il n'a donc pas acces à l'etat du booleen.
    Comme ca :
    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
    while (termine == false){
     
           //.... traitement
          // 1ere boucle for
          for (...){
     
     
          }
     
           //.... traitement
          // 2e boucle for
          for (...){             // <--- si le thread s'arrete ici l'etat termine n'a pas changé
     
     
          }
     
     
          //.... traitement
          // 3e boucle for
          for (...){
     
     
          }
     
     
     
    }
    Je pourrais verifier l'etat de "termine" avant chaque instruction mais le traitement fais des centaines de lignes, je ne me vois pas faire ca 700 fois !!

    Si quelq'un a une astuce je suis preneur

  7. #7
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 182
    Par défaut
    Citation Envoyé par dragohn
    Bonjour,

    vaut il mieux utiliser votre solution Mose, ou passer par un bloc try/catch/finally et capturer l'exception ThreadAbortException pour fermer le fichier/finir le traitement.
    Ma question peut sembler de novice (je le suis), et je dois admettre que j'avais pensé à traiter ça que via l'exception... à faire ou éviter?
    j'ai egalement essayé de fermer le fichier dans le bloc ThreadAbortException mais ca ne donne rien.

  8. #8
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Citation Envoyé par dragohn
    Bonjour,

    vaut il mieux utiliser votre solution Mose, ou passer par un bloc try/catch/finally et capturer l'exception ThreadAbortException pour fermer le fichier/finir le traitement.
    Ma question peut sembler de novice (je le suis), et je dois admettre que j'avais pensé à traiter ça que via l'exception... à faire ou éviter?
    L'exception c'est la solution barbare et un peu crade. qui plus est, en terme de perf c'est pas terrible : le runtime peut mettre une seconde ou deux avant de rendre la main.
    La solution du booléan est plus propre, et elle permet à ton thread de finir au moins le traitement qu'il était en train de faire.

    Ex : je copie n fichiers dans mon thread. A chaque fichier de vérifie mon booléen.
    Si je kill + exception : le ficher en cours de copie a-t-il été complètement copié / partiellement copié / pas du tout copié ? On n'en sait rien
    alors qu'avec la solution booléan, le traitement s'interromp après la copie complète d'une fichier

  9. #9
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Citation Envoyé par voyageur
    j'ai essayé cette technique mais le probleme est que le thread est arreté à la premiere rentrée dans la boucle, il n'a donc pas acces à l'etat du booleen.
    Quand tu me dit "le thread s'arrête ici", j'ai un peu de mal à comprendre.. qui l'arrête ?

    Je me suis sans doute mal exprimé.
    En fait, pour arrêter ton thread, tu n'a qu'une seule chose à faire : mettre le booléan terminé à vrai.

    Ensuite, il ne s'agit pas de créer une boucle spécialement pour ça. Je partais du principe que ton thread fonctionnait déjà avec une boucle. Dans ton exemple, il s'agit de tes boucles for.

    Dans chacune de ces boucles, tu rajoutes la condition d'arrêt !termine (ça retourne déjà un booléan, pas la peine de faire termine == false)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(int i = 0; (i < max) && !termine; i++)
    {...}
    Citation Envoyé par voyageur
    Je pourrais verifier l'etat de "termine" avant chaque instruction mais le traitement fais des centaines de lignes, je ne me vois pas faire ca 700 fois !!
    En fait, tu peux ne faire ça qu'à certaines étapes clef.
    Par exemple, avant tous les traitements longs.

  10. #10
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 182
    Par défaut
    Citation Envoyé par Mose
    Dans chacune de ces boucles, tu rajoutes la condition d'arrêt !termine (ça retourne déjà un booléan, pas la peine de faire termine == false)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(int i = 0; (i < max) && !termine; i++)
    {...}
    En fait, tu peux ne faire ça qu'à certaines étapes clef.
    Par exemple, avant tous les traitements longs.
    je suis d'accort avec toi pour verifier l'etat du booleen dans chacune des boucles for.
    Mais si la demande d'arreter le thread intervient entre deux boucles for ?
    Car il y a des centaines d'instructions entre chaque boucle for !!

    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
    while (termine == false){
     
           //.... traitement
          // 1ere boucle for
          for (...){
     
     
          }
     
          // ... beaucoup d'instructions aussi entre les boucles for
     
           //.... traitement
          // 2e boucle for
          for (...){             
     
     
          }
     
     // ... beaucoup d'instructions aussi entre les boucles for
     // <--- si la demande d'interruption intervient ici je suis donc obligé d' attendre l'entree dans la prochaine boucle for pour verifier l'etat du booleen, ca risque d'etre trop long !! 
     
     
          //.... traitement
          // 3e boucle for
          for (...){
     
     
          }
     
     
     
    }

  11. #11
    Membre confirmé Avatar de dragohn
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Août 2006
    Messages : 85
    Par défaut
    Citation Envoyé par Mose
    L'exception c'est la solution barbare et un peu crade. qui plus est, en terme de perf c'est pas terrible : le runtime peut mettre une seconde ou deux avant de rendre la main.
    La solution du booléan est plus propre, et elle permet à ton thread de finir au moins le traitement qu'il était en train de faire.

    Ex : je copie n fichiers dans mon thread. A chaque fichier de vérifie mon booléen.
    Si je kill + exception : le ficher en cours de copie a-t-il été complètement copié / partiellement copié / pas du tout copié ? On n'en sait rien
    alors qu'avec la solution booléan, le traitement s'interromp après la copie complète d'une fichier
    Merci beaucoup pour l'explication, je comprends mieux maintenant.
    Donc toujours tenter de préférer une solution de terminaison propre, plutot que de se servir des exceptions pour gérer ça.

    voyageur > je comprends ce que tu veux dire, je me posais la même question. Je me suis dit que comme pour tes boucles for, tu finis une boucle avant de sortir, pour ton code intermédiaire avec la solution du booléen tu effectues tout le code à partir du moment où tu le commences. En gros mettre un if(!termine){ toutes tes instructions intermédiaires }, et même si ton termine change d'état tu finis ton bloc if (ou découper tes centaines de lignes intermédiaires en petit blocs pour tester et arrêter plus tôt).

    Je ne vois que ça (à mon niveau, donc pas spécialement le must ). Autrement comme j'ai dit, je ne connais que les exceptions pour décrocher à n'importe quel moment, de façon "propre" je ne vois pas.
    Connaitre la solution au final m'intéresse donc beaucoup aussi

  12. #12
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Citation Envoyé par voyageur
    je suis d'accort avec toi pour verifier l'etat du booleen dans chacune des boucles for.
    Mais si la demande d'arreter le thread intervient entre deux boucles for ?
    Car il y a des centaines d'instructions entre chaque boucle for !!
    Réfléchi en temporisation, pas en position dans le code.
    Si ces centaines d'instructions sont toutes simples, alors tu t'en tapes, elles seront exécutées en 1,5 ms et ton thread s'arrêtera avec 1,5ms de retard par rapport au moment où tu le demandes.
    Si t'as des grosses instructions, genre une copie de fichier, alors fait un test avant.
    Le but c'est de "découper" ton traitement en entités indivisibles, histoire que ton arrêt ne violente pas ces traitements.

  13. #13
    Membre Expert Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Par défaut
    Citation Envoyé par dragohn
    Autrement comme j'ai dit, je ne connais que les exceptions pour décrocher à n'importe quel moment, de façon "propre" je ne vois pas.
    Connaitre la solution au final m'intéresse donc beaucoup aussi
    La solution finale consiste, dès le départ, à bien coder ton thread.
    Je trouve bizarre qu'il y ai des dizaines de boucles et des centaines d'instruction entre elles dans un thread.
    * Est-ce que les traitement ont été bien factorisés ? ou est-ce que les boucles sont des copiés collés paske c'était plus rapide de coder comme ça ?

    Sinon, une solution canonique et propre à des traitement lourds consiste à faire une gestion d'état.
    Exemple :
    * Dans mon thread je dois faire successivement les traitements A, B, C, D et E (tous différents)
    * Je code mon thread comme une machine à états :
    * * une variable "état" (entier) valant de 0 à 5
    * * je ne fais qu'une seul boucle principale
    * * à chaque itération, je teste mon état, si c'est 0, je fais "A", etc...
    * * à la fin de l'itération, j'incrémente mon état.
    * * si je suis à l'état 5 (ou +), alors j'ai fini, je sors de ma boucle et mon thread se termine

    Du coup, pour sortir de mon thread proprement, il me suffit de passer l'état à 5
    (On peut aussi garder un booléan pour ça, si on veut distinguer la sortie normale de la sortie "forcée")
    En plus, si un jour je dois changer mon code pour faire C avant B, c'est hyper simple à modifier

  14. #14
    Membre confirmé Avatar de dragohn
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Août 2006
    Messages : 85
    Par défaut
    Merci beaucoup pour l'explication!
    C'est vraiment clair, et finalement très logique

    Encore merci!

Discussions similaires

  1. arreter l'execution d'un thread en java
    Par albokos dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 21/05/2008, 04h13
  2. interruption et reprise d'un thread
    Par Virgile le chat dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 09/07/2007, 14h28
  3. Interruption et reprise d'un Thread
    Par michaeljeru dans le forum Concurrence et multi-thread
    Réponses: 11
    Dernier message: 12/04/2007, 19h17
  4. Interruption et reprise d'un Thread
    Par Nuro dans le forum Concurrence et multi-thread
    Réponses: 1
    Dernier message: 28/02/2007, 22h34
  5. Pause et reprise d'un thread
    Par raggadoll dans le forum Linux
    Réponses: 5
    Dernier message: 03/07/2003, 21h22

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