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

VB.NET Discussion :

RaiseEvent bloque Abort d'un thread


Sujet :

VB.NET

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 14
    Par défaut RaiseEvent bloque Abort d'un thread
    Bonjour @Tous

    Dans mon aventure avec les threads je rencontre un nouveau pb,
    Quand je fais un Abort sur un thread en cours, il me leve bien l'exception ThreadAbortException mais ca bloque...a priori c'est mon RaiseEvent qui l'emerde. Pourquoi ?

    Lancement du thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Public Sub Exporter()
            If Exporting Then
                Return
            End If
     
            _Durée = System.Environment.TickCount
            _Exporting = True
            _ExportThread = New Thread(New ThreadStart(AddressOf ThreadProcedure))
            _ExportThread.IsBackground = True
            _ExportThread.Start()
        End Sub
    Procedure du thread
    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
        Private Sub ThreadProcedure()
            _Erreur = Nothing
     
            Try
                RaiseEvent DébutExport(Me, New DébutExportEventArgs(_Chemin))
                _ugeXLS.Export(_Grid, _Chemin)
                _Statut = Enums.StatutExport.Succès
     
            Catch ex As Exception
                _Erreur = ex.Message
                _Statut = Enums.StatutExport.Echec
     
            Finally
                _Exporting = False
                _Durée = System.Environment.TickCount - _Durée
                RaiseEvent FinExport(Me, New FinExportEventArgs(_Statut, _Durée, _Chemin, _Ouvrir, _Erreur))
     
     
            End Try
     
        End Sub
    Arret du thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        Public Sub ArreterExport()
            If Not _Exporting Then
                Return
            End If
     
            If _ExportThread.IsAlive Then
                _ExportThread.Abort()
                _ExportThread.Join()
            End If
     
            _Statut = Enums.StatutExport.Annulation
            _ExportThread = Nothing
            _Exporting = False
        End Sub

  2. #2
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    Essaye de rajouter ton event la :
    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
        Private Sub ThreadProcedure()
            _Erreur = Nothing
     
            Try
                RaiseEvent DébutExport(Me, New DébutExportEventArgs(_Chemin))
                _ugeXLS.Export(_Grid, _Chemin)
                _Statut = Enums.StatutExport.Succès
     
            Catch ex As Exception
                _Erreur = ex.Message
                _Statut = Enums.StatutExport.Echec
                RaiseEvent FinExport(Me, New FinExportEventArgs(_Statut, _Durée, _Chemin, _Ouvrir, _Erreur))
            Finally
                _Exporting = False
                _Durée = System.Environment.TickCount - _Durée
                RaiseEvent FinExport(Me, New FinExportEventArgs(_Statut, _Durée, _Chemin, _Ouvrir, _Erreur))
     
     
            End Try
     
        End Sub
    C'est normal qu'il n'exécute pas ce qu'il y a dans le finally ! Mais normalement on arrête pas un thread mais on le laisse se terminer...
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 14
    Par défaut
    C'est pareil, la console me donne:"Une exception de première chance de type 'System.Threading.ThreadAbortException' s'est produite dans mscorlib.dll"

    Bah je fais comment pour arreter mon export? (j'ai pas la main sur le .Export)
    Merci pour ta réponse

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    Salut Emap,

    Ton RaiseEvent, il n'appellerai pas une methode qui invoke un thread (par exemple celui qui est en Join() ) ? Si oui, c'est normal que ca bloque. Tu as ton thread appelant (je suppose celui de l'UI) qui est en join() sur un thread qui lui meme cherche à invoquer ce dernier, bref un bon gros deadlock des familles. =)

    Si tu dois arreter ton thread (d'ailleurs comme le sous-entend Aspic .Abort() is Evil !), essaie plutot de gerer ca avec un booleen que le thread d'export controlera en fin d'export pour savoir ce qu'il doit faire (s'arreter simplement, reporter le cancel, whatever). Et ne Join pas ton thread appelant sur le thread d'export, fais simplement une requete de cancel, apres c'est le thread d'export qui gerera ca et se terminera comme un grand.

    Bon courage.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 14
    Par défaut
    mmm j'ai pas tout pigé

    Le pb est que la procedure de mon thread (.Export) je n'ai pas la possibilité de l'arreter, c'est donc pour ca que je fais un abort.

    Mon RaiseEvent pointe un délégué (ca y est j'ai compris:p)
    => Public Delegate Sub FinExportEventHandler(ByVal sender As Object, ByVal e As FinExportEventArgs)
    FinExportEventArgs c'est donc ma classe qui encapsule mes valeurs d'event.

    Ce public delegate est déclaré avant ma classe de cette facon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Public Delegate Sub FinExportEventHandler(ByVal sender As Object, ByVal e As FinExportEventArgs)
     
    Public Class ExportXLS
        Public Event FinExport As FinExportEventHandler
     
    ...
    et apres c'est ce que j'ai mis plus bas.
    Donc si je comprends bien, quand je fais MonThread.Abort (+ .Join) je peux plus faire mon RaiseEvent puiqu'il est géré par mon thread en attente d'arret ?

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 14
    Par défaut
    ben si j'enleve le join ca marche (j'suis con, il s'attends lui meme!)

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    Citation Envoyé par emap Voir le message
    et apres c'est ce que j'ai mis plus bas.
    Donc si je comprends bien, quand je fais MonThread.Abort (+ .Join) je peux plus faire mon RaiseEvent puiqu'il est géré par mon thread en attente d'arret ?
    En fait, ta fonction ArreterExport(), elle est appelée par ton UI (genre sur un bouton). De la, ton thread d'UI demande au thread d'export de se suicider jusque la ca va, abort() c'est pas top, mais ca marche. Une fois que la requete d'abort a été envoyé, ton thread d'UI (celui qui a appelé abort) va se bloquer jusqu'a ce que ton thread d'export soit terminé (ca c'est pas bien, il ne faut jamais pauser ou interrompre un thread d'UI => risque probable de freeze de ton interface == tres enervant). Bref, en se suicidant ton thread d'export, lance un event (FinExport) qui, je le suppose fortement, doit avoir comme abonné des methodes liées à ton interface (genre de mise à jour, de report etc) et donc doivent invoquer le thread d'UI pour mettre à jour ces données.

    Au final, la situation est :
    -Ton thread d'UI est sleepé, et attend que le thread d'export se termine.
    -Ton thread d'export essaie d'appeler ton thread d'UI et ne se terminera que quand il aura reussi.

    Les deux s'attendent entre eux, et aucun des deux ne se debloquera, tu es coincé.

    Bref, la solution ( si tant est que l'hypothese est la bonne, ca peut etre autre chose) est comme tu l'a fais, de ne pas sleeper ton UI (c'est une consideration applicable ici, et de maniere generale aussi, on ne touche pas un thread d'UI (j'entends sleep, join ou autre) sinon tu as de tres grandes chances de voir des gels et plantages de ton interface).

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 14
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    If _ExportThread.IsAlive Then
                _ExportThread.Abort()
                _ExportThread.Join()
            End If
    pourtant la, c'est bien mon thread d'export qui est .Join. Ca veut bien dire qu'il attent la fin du abort non ?

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    _ExportThread.Join() bloquera le thread appelant tant que _ExportThread n'est pas terminé, d'ou le blocage. =)

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

Discussions similaires

  1. Abort sur un thread appelant socket.receive
    Par safisafi dans le forum VB.NET
    Réponses: 1
    Dernier message: 26/10/2009, 10h01
  2. [Thread ] Thread bloqué
    Par lykim1982 dans le forum Visual C++
    Réponses: 1
    Dernier message: 07/06/2007, 16h38
  3. Arreter un thread qui "bloque" sur un socket
    Par J-F dans le forum Concurrence et multi-thread
    Réponses: 2
    Dernier message: 12/12/2006, 00h04
  4. [API Win32 sans MFC] Lecture port série: thread bloqué
    Par dacid dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 24/05/2006, 13h34
  5. [Threads et interface] le thread bloque tout
    Par meda dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 28/10/2004, 16h52

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