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 :

Arret de thread.


Sujet :

C#

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 391
    Par défaut Arret de thread.
    Bonjour

    J'ai dans une DLL un object possédant un thread linéaire.
    Je veux dire un traitement successif sans boucle. Si une erreur est rencontrée on quitte, si le thread arrive à la fin il doit s’arrêter.
    Afin de contrôler les erreurs toutes les instructions sont englobées dans un try catch.

    j'utilise cette DLL dans un projet winform ou je peut creer plusieurs de ces object et lancer le thread de chacun en parrallele.

    pour etre sure que tous mes thread sont terminés, j'ajoute a mon thread principal un join de chacun.


    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
       private void flashReaders()
            {
                if (nbReadertoFlash > 0)
                {
                    nbReaderFlashed = nbReadertoFlash;
                    foreach (reader rd in readerList)
                    {
                        if (rd.needFirmwareUpdate)
                        {
                            rd.theReader.FlashFirmware(rd.firmwarePath);
                            System.Threading.Thread.Sleep(100);                      
     
                            rd.theReader.flashThread.Join();
                        }
                    }
     
                }
                else
                {
                    DisposeAllreader();
                }
            }
    En exécutant ce code, tout les thread fonctionnent et je n'ai jamais d'exception levée. Je continue donc ce code dans la fonction DisposeAll Reader().

    Cette fonction me permet de détruire tout mes object et de lancer le Close() de la fenêtre.En testant les thread utilisés pour chacun des object, il en restant des alive ???? bien que je notifie bien que je suis sortie de ce thread et que j'ai passé les join.
    Si j'essaye un abort, l'app freeze sans erreur. Sans l'abort avec le bloc try catch dans le thread , le debugger me renvoi un erreur inter thread de la form ?

    Je ne vois pas pourquoi le thread est toujours alive.
    Je ne comprend pas pourquoi le message renvoyé et un probleme inter thread alors que j'utilise une textbox de la form avec un .invoke.

    Si vous avez une piste je suis preneur

    Cordialement

  2. #2
    Rédacteur
    Avatar de WOLO Laurent
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Mars 2003
    Messages
    2 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 741
    Par défaut
    Tu dois utiliser un best practice :
    1-Regardes du côté des call-backs(C'est la méthode qui notifie qu'elle vient de terminer son execution);
    2-Utilises les threads de pool (Création et gestion moins couteuse en ressource);

    Bonne chance

    Découvrez la FAQ de MS SQL Server.
    La chance accorde ses faveurs aux esprits avertis !

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 391
    Par défaut
    bonjour

    En continuant a debugger voici quelque résultat étonnant.

    En lancant tel quel mon application et en enlevant le close() de ma fonction dispose en en fermant par la croix rouge : Pas de probleme.

    En laissant le close et en enlevant les threads qui s'execute successivement : pas de probleme.

    En deplacant le close en laissant les thread : toujours le probleme.

    En recuperant le nom de ma fenetre et en fermant par un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PostMessage(hWnd, WM_CLOSE, 0, 0);
    Pas de problème.

    Si quelqu'un peut m'expliquer la difference des close et ce qui se passe, la je suis dans le flou total.

    Cordialement

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    un control (form hérite de control) ne peut etre modifié que par le thread qui l'a créé
    depuis un autre thread ca plante "inter thread"
    pour revenir sur le thread d'un control temporairement tu peux utiliser un délégué (pour dire au thread du control d'exécuter le délégué plutot que de le faire depuis le thread)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 391
    Par défaut
    Bonjour

    Merci Pol63 pour cette explication, mais je ne lance pas le Close du thread, mais mon thread crée un event de fin et sort.
    La forme est abonnée a cet évènement. Quand l’évènement est notifié, je lance la fonction de fermeture donc de la form mais pas 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
     
      rd.theReader = new rfidReader();
                    rd.theReader.TextBox = textBox;
                    rd.theReader.NotifyEvent += new NotifyHandlerDelegate(NotifyEvent);
     
    private void NotifyEvent(object sender, SDK_SC_RfidReader.rfidReaderArgs args)
            {
    case rfidReaderArgs.ReaderNotify.RN_FirmwareCorruptedHexFile:
                    case rfidReaderArgs.ReaderNotify.RN_FirmwareFailedToFinish:
                    case rfidReaderArgs.ReaderNotify.RN_FirmwareSuccedToFinish:
     
     
                    if (--nbReaderFlashed == 0)
                        DisposeAllreader();
     
                    break;
    }
    et dans la fonction dispose qui marche ( sort sans inter thread problème)
    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 void DisposeAllreader()
            {
                Thread.Sleep(1000);  //wait for all reset
                foreach (reader rd in readerList)
                {
                    addMessage("[xxxxxxxx]", "clean " + rd.serialNumber, ">");
     
     
                    rd.theReader.Dispose();
     
                    if (rd.firmwarePath != null)
                    {
                        addMessage("[xxxxxxxx]", "delete file to " + rd.firmwarePath, ">");
                        File.Delete(rd.firmwarePath);
                    }      
                }
                IntPtr hWnd = FindWindow(null, this.Text);
                if (hWnd.ToInt32() != 0) 
                    PostMessage(hWnd, WM_CLOSE, 0, 0);            
            }

    et la même qui marche pas avec le close
    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
     
     private void DisposeAllreader()
            {
                Thread.Sleep(1000);  //wait for all reset
                foreach (reader rd in readerList)
                {
                    addMessage("[xxxxxxxx]", "clean " + rd.serialNumber, ">");
     
     
                    rd.theReader.Dispose();
     
                    if (rd.firmwarePath != null)
                    {
                        addMessage("[xxxxxxxx]", "delete file to " + rd.firmwarePath, ">");
                        File.Delete(rd.firmwarePath);
                    }      
                }
                Close();        
            }
    cordialement

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    Citation Envoyé par ricky78 Voir le message
    Bonjour

    Merci Pol63 pour cette explication, mais je ne lance pas le Close du thread, mais mon thread crée un event de fin et sort.
    La forme est abonnée a cet évènement. Quand l’évènement est notifié, je lance la fonction de fermeture donc de la form mais pas du thread.

    j'ai pas lu ton code, mais l'exécution du code lié à un évènement déclenché depuis un thread se fait sur le même thread
    ce n'est pas parce que le code est sur le form qu'il est exécuté sur le thread du form !
    bref il faut revenir sur le thread principal pour faire le close (via un délgué et this.invoke par exemple)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 66

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut arreter un thread,thread abort, catch ThreadAbortException
    bonjour ricky
    pour arreter un thread parmi -n thread paralleles-demarres à partir d'un thread principal il suffit d'appeler Abort.Thread avec numero de thread et de catcher ThreadAbortException dans la tache gere par ce thread.
    code exemple pour etre plus clair:
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
     
    'Forme lance la methode shared Main de la classe TesteurAbortThread
    Public Class Form1
        Public Sub New()
     
            ' Cet appel est requis par le Concepteur Windows Form.
            InitializeComponent()
     
            ' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
            Me.TextBox1.Multiline = True
            Me.TextBox1.ScrollBars = ScrollBars.Both
        End Sub
        '
        'Recupere le deroulement tache dans le TextBox1
        Private Sub btnTesteurAbort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTesteurAbort.Click
            'demarre les threads
            TesteurAbortThread.Main()
            'Recupere le deroulement tache dans le TextBox1
            Me.TextBox1.Text = Me.TextBox1.Text & TesteurAbortThread.strMessage & vbCrLf
     
        End Sub
    End Class
     
    'Classe  manager d'un groupe de threads
    Option Strict On
    Imports System
    Imports System.Threading
    Public Class TesteurAbortThread
        'permet de recuperer le deroulement des 2 taches
        '"Incremeteur" & "Decrementeur"
        Public Shared strMessage As String
        Shared Sub Main()
            ' cree une instance de cette classe
            Dim objAbortThread As New TesteurAbortThread()
            TesteurAbortThread.strMessage = ""
            ' Executer en dehors de  Main
            objAbortThread.FaireTest()
        End Sub 'Main
     
        Public Sub FaireTest()
            ' cree un tableau de 3 threads sans noms
            Dim mesThreads As Thread() = _
                {New Thread(New ThreadStart(AddressOf Decrementeur)), _
                New Thread(New ThreadStart(AddressOf Incrementeur)), _
                New Thread(New ThreadStart(AddressOf Incrementeur))}
     
            ' demarre chaque thread
            Dim numThread As Integer = 0
            Dim monThread As Thread
            For Each monThread In mesThreads
                monThread.IsBackground = True
                monThread.Start()
                monThread.Name = "Thread-" + numThread.ToString()
                numThread += 1
                TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Started demarre " & monThread.Name & vbCrLf
                'intervalle de temps entre chaque thread 50 ms
                Thread.Sleep(50)
            Next monThread
     
            ' Apres avoir demarre les 3 threads
            ' Demander au 1er  thread  d'abandonner(qui gere Decrementer)
            mesThreads(0).Abort()
     
            ' Attendre la fin des autres threads  avant de faire un resume sur thread principal
            Dim objTread As Thread
            For Each objTread In mesThreads
                objTread.Join()
            Next objTread
     
            ' Apres la fin de tous les threads , imprimer un message
            TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Tous les threads sont termines..." & vbCrLf
        End Sub 'FaireTest
     
     
        'Tache1 Compteur à partir 1000 à rebours
        Public Sub Decrementeur()
            Try
                Dim I As Integer
                For I = 1000 To 0 Step -1
                    'Console.WriteLine("Thread {0}. Decrementeur: {1}", _
                    '    Thread.CurrentThread.Name, i)
                    TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Thread . Decrementeur: " & Thread.CurrentThread.Name & " " & I.ToString & vbCrLf
                    Thread.Sleep(0)
                Next I
                'ICI LE CATCH ThreadAbortException qui permet l'arret
            Catch e As ThreadAbortException
                TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "***Thread  abandonné! Nettoyage resources..." & Thread.CurrentThread.Name & vbCrLf
            Finally
                TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Thread  abandonné En train de Sortir.... " & Thread.CurrentThread.Name & vbCrLf
            End Try
        End Sub 'Decrementeur
     
        'Tache2 Compteur jusqu'à  1000
        Public Sub Incrementeur()
            Try
                Dim I As Integer
                For I = 0 To 1000
                    TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Thread . Incrementeur: " & Thread.CurrentThread.Name & " " & I.ToString & vbCrLf
                    Thread.Sleep(0)
                Next I
            Catch
            Finally
                TesteurAbortThread.strMessage = TesteurAbortThread.strMessage & "Thread  En train de Sortir normalement..... " & Thread.CurrentThread.Name & vbCrLf
            End Try
        End Sub 'Incrementeur
    End Class 'TesteurAbortThread
    en resume:
    si l'on veut "aborter" un thread -x- quelconque il suffit de catcher dans- chaque tache -i-execute par ce thread - l'exception ThreadAbortException.
    bon code.......

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    .abort est pas super propre, parce que l'exception peut etre déclenché dans le code du framework et pourrait avoir des conséquences
    gérer un arret manuellement est plus approprié
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 66

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut arret de thread à partir du thread principal
    bonjour pol
    je ne vois aucune methode dans l'api qui permettrait d'arreter un thread à partir du thread principal mis à part Thread.Abort.
    Le seul moyen est de gerer proprement l'exception ThreadAbortException
    dans le Catch et dans le Finally en y incluant un petit appel à ResetAbort pour permettre au "thread abandonne" de terminer la tache en cours et un appel à Thread.Join dans le Thread Principal pour attendre une fin "propre" du "thread abandonne" .
    code extrait de l'API MSDN à l'attention de ricky:
    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
     
    Imports System
    Imports System.Threading
    Imports System.Security.Permissions
     
     
    Public Class ThreadWork
       Public Shared Sub DoWork()
          Try
             Dim i As Integer
             For i = 0 To 99
                Console.WriteLine("Thread - working.")
                Thread.Sleep(100)
             Next i
          Catch e As ThreadAbortException
             Console.WriteLine("Thread - caught ThreadAbortException - resetting.")
             Console.WriteLine("Exception message: {0}", e.Message)
             Thread.ResetAbort()
          End Try
          Console.WriteLine("Thread - still alive and working.")
          Thread.Sleep(1000)
          Console.WriteLine("Thread - finished working.")
       End Sub 'DoWork
    End Class 'ThreadWork
     
     
    Class ThreadAbortTest
       Public Shared Sub Main()
          Dim myThreadDelegate As New ThreadStart(AddressOf ThreadWork.DoWork)
          Dim myThread As New Thread(myThreadDelegate)
          myThread.Start()
          Thread.Sleep(100)
          Console.WriteLine("Main - aborting my thread.")
          myThread.Abort()
          myThread.Join()
          Console.WriteLine("Main ending.")
       End Sub 'Main
    End Class 'ThreadAbortTest
    l'Api MSDN signale que AppDomain utilise cette methode lors de son dechargement,à toutes fins utiles....
    bon code......

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    même le backgroundworker implémente la méthode propre donc c'est que c'est faisable
    à savoir un booléen à setter quand on veut arreter le thread et vérifier ce booléen dans le thread

    .interrupt n'a pas l'effet de bord dont je parle par rapport au .abort, peut etre en a-t-il d'autres
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. Réponses: 6
    Dernier message: 27/10/2005, 12h58
  2. [Thread] comment arreter un thread qui execute une methode b
    Par Cyber@l dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 04/08/2004, 10h51
  3. j'arrive pas a arreter mon thread d'arriere-plan
    Par ms91fr dans le forum Langage
    Réponses: 6
    Dernier message: 06/06/2003, 21h36
  4. probleme a l'arret de threads
    Par Sei dans le forum C++Builder
    Réponses: 5
    Dernier message: 16/12/2002, 12h15

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