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 :

lancer un exception


Sujet :

C#

  1. #1
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut lancer un exception
    Bonjour,

    voila mon pb, j'ai une ligne de code qui reste, d'une manière aléatoire, bloquée...on ne sait pas le pourquoi pr l'instant.
    pour débloquer la situation, y-a t il un moyen de dire au programme si l'exécution dure plus de 10 min alors lancer une exception ?

    Merci bcp!!

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    Ma foi, juste avant d'appeler la ligne qui bloque, il suffit de créer un thread qui attendra un waitevent. Si 10 mins s'écoulent, Thread.Abort est appelé, levant une exception sur le thread d'origine où se situe la ligne fautive.

    Code c# : 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
    public sealed class Watchdog : IDisposable
    {
       private Thread _monitorThread;
       private Thread _threadToWatch;
       private EventWaitHandle _waitHandle;
     
       public Watchdog()
       {
          _threadToWatch = Thread.Current;
          _waitHandle = new ManualResetEvent(false);
          _monitorThread = new Thread(Run);
          _monitorThread.Background = true;
          _monitorThread.Start();
       }
     
       // Attend jusqu'à 10mins puis avorte threadToWatch si différent de null
       private void Run()
       {
           _waitHandle.WaitOne(10 * 60 * 1000, false);
     
          // Avortement du thread si cette instance n'a pas été disposée proprement
          // Copie locale de threadToWatch en cas de chgt de thread entre le test et abort
          var threadToAbort = _threadToWatch;
          if (threadToAbort != null) threadToAbort.Abort();
       }
     
       // Appelé quand tout s'est bien passé.
       public void Dispose()
       {
           // threadToWatch n'a pas bogué, pas besoin de l'avorter.
           _threadToWatch = null;
     
          // Réveil de monitorThread qui va se terminer en silence.
           _waitHandle.Set();
       }
    }

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    using(new Watchdog())
    {
        DoSomeBuggyStuff();
    }

  3. #3
    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 : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    le mieux est de trouver pourquoi la ligne bloque et de corriger le bug
    pour ca il faut que tu nous donnes la ligne en question

    si c'est un thread séparé, tu peux en effet l'interrompre s'il dépasse plus de tant de temps, pour ca il faut au mieux être dans une boucle
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    Merci pour vos réponse...mais j'ai du mal à comprendre l'exemple de DonQuiche.

    est-ce qu'il ne suffit pas de faire un truc du genre...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Thread rtThread = new Thread(new ThreadStart(Start));
                rtThread.Start();
                System.Threading.Thread.Sleep(10000);
               l'instruction en question
               rtThread.Join();
    merci

  5. #5
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Non, ça n'a pas du tout le même effet.

    Première remarque : ton "sleep" a seulement pour effet de faire dormir le thread d'origine (thread1) pendant 10s pendant que thread2 travaille (pour faire quoi ? Que contiendrait ce "start" ?) avant de lancer l'instruction boguée. En gros tu laisses 10s d'avance à thread2. Ça n'a aucun intérêt.

    Deuxièmement, tu dis à thread1 qu'une fois l'instruction boguée terminée (sans la forcer à se terminer), il faut ensuite attendre la fin de thread2. Là encore, tu n'accomplis rien de ce que tu voulais faire : notamment tu ne forces pas le thread d'origine à interrompre l'instruction boguée.

    Fondamentalement, il te faut un système qui, après 10s, avortera le thread d'origine si celui-ci ne s'est pas exécuté correctement. Si tout se passe bien, c'est la séquence "constructeur - début de run - dispose - fin de run" qui est exécutée. S'il y a un problème, c'est la séquence "constructeur - début de run - attente de 10mins - fin de run".


    Concernant mon code, avant toute chose sais-tu comment fonctionne le bloc "using" et "IDisposable" ? Que je sache quelle partie te pose problème.

  6. #6
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    ok merci, alors je vais me pencher un peu plus sur ton exemple...

  7. #7
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Pour te donner un coup de main, compare donc ces deux cas.

    Si tout se passe bien, la séquence est la suivante :
    * [thread1] Watchdog.Constructeur
    * [thread2] Watchdog.Run - Début jusqu'à WaitOne()
    * [thread1] Instruction boguée qui ne bogue pas cette fois
    * [thread1] Watchdog.Dispose
    * [thread2] Watchdog.Run - Reprise et fin immédiatement après Set() (dans Watchdog.Dispose)
    * [thread1] Pas d'exception, tout continue normalement.


    Si en revanche il y a un bug :
    * [thread1] Watchdog.Constructeur
    * [thread2] Watchdog.Run - Début jusqu'à WaitOne()
    * [thread1] Instruction boguée, thread1 est planté
    * [thread2] Watchdog.Run - Reprise et fin après 10mins d'attente. Appel de thread1.Abort()
    * [thread1] Levée de ThreadAbortException

  8. #8
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    merci,
    ça tournera ce soir, je vous tiendrai au courant

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    Bonjour,
    Malheureusement, ça n'a pas marché...mon prog est resté bloqué...

    voila ce que j'ai fait...
    + j'ai créé une nvelle classe Watchdog à mon projet
    + ensuite sur la ligne qui se bloque, j'ai fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    using (new Watchdog())
                    {
                        var = new AdxRtList(); //la ligne qui se bloque
                    }
    Voyez-vous svp ce qui ne va pas ??
    merci

  10. #10
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Malheureusement, il me faudrait plus de détails. Voilà quoi faire pour tester la bête :

    1. Changer la valeur passée à WaitOne (10 mins) par une autre plus courte (1000 ms)
    2. Utiliser le code suivant :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    using(var watchdog = new Watchdog())
    {
       Thread.Sleep(100000); // Simule un blocage du thread principal en l'endormant.
    }
    3. Mettre un breakpoint après WaitOne dans Watchdog.Run() et lancer le tout.

  11. #11
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    J'ai fait le test. Le thread est avorté et le prog s'arrête.

    J'ai une question, après l'avortement du thread on passe dans la fonction dispose. c'est normal ??
    merci bcp!

  12. #12
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Heureux pour toi que ça marche, ça m'étonnait aussi.

    Oui, il est normal qu'on aille dans la fonction Dispose, celle-ci est appelée même en cas d'exception : IDisposable et using ont été ajoutés à l'origine pour fournir un pattern garantissant le nettoyage en toutes circonstances des ressources non-managées. En effet, notre utilisation de "using" est équivalente au code ci-dessous :

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var watchdog = new Watchdog();
    try
    {
       Thread.Sleep(100000);
    }
    finally
    {
        watchdog.Dispose();
    }

    L'appel tardif à Dispose est inutile ici mais il ne pose pas de problème puisque "Run" a déjà terminé. Au passage, note qu'il est impossible d'arrêter une ThreadAbortException : même si tu l'interceptes via un bloc "catch", celle-ci sera relancée à la fin du bloc.

  13. #13
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    le pb est que ça marche bien avec le test du sleep(1000).
    mais avec le blocage aléatoire de l'instruction "new" ça n'a pas l'air de marcher...

    je vais le laisser encore tourner qq jours et voir...

    merci bcp de ton aide!

  14. #14
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    Bonjour,

    je suis toujours bloqué...

    j'ai essayé de diminuer le temps d'attente...ainsi lorsque l'instruction se bloque, le programme s'arrête rapidement...
    mais, cela fait planté mon programme même quand l'instruction ne se bloque pas parce l'exécution normale de mon prog dure plus que le temps d'attente...

    Y-a t il un moyen de lier le temps d'attente juste à l'instruction qui se plante ??

    Merci

  15. #15
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    C'est impossible. Le seul moyen de savoir que l'instruction a planté, c'est lorsqu'elle dépasse un certain temps d'attente. Donc tu dois garder un temps d'attente assez long pour que celui-ci signifie bel et bien un plantage.

    Cela dit, si ton opération a d'autres symptômes particuliers lorsqu'elle plante (exemple : activité CPU devenant nulle), on peut s'en servir.

  16. #16
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    Je me suis peut être mal exprimé...
    est ce que c normal que j'ai une thread.abrot quand l'instruction ne se bloque pas. je m'explique :

    j'ai mis comme temps d'attente 5min
    quand il n y a pas de plantage, mon prog s'execute en 10 min

    Je constate la chose suivante :

    Watchdog.Constructeur
    Watchdog.Run
    Instruction boguée qui ne bogue pas cette fois
    Watchdog.Dispose
    Le prog continue normalement

    MAIS au bout de 5min, j'ai un thread.abort qui se lance et mon prog s'arrête...??

  17. #17
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Ok, c'est supposé ne pas pouvoir arriver avec le code tel qu'il est. Deux choses me viennent à l'esprit :
    * Une optimisation malencontreuse, évitable en déclarant le membre "_threadToWatch" comme "volatile" : private volatile Thread _threadToWatch;. Ça me semblerait étrange que le compilateur cherche à faire cette optimisation ici mais sait-on jamais.
    * Le cas où tu aurais recopié la première version que j'avais postée : dans les instants qui avaient suivi j'avais apporté quelques modifications, dont une correction de bug. Je t'invite donc à vérifier ligne par ligne que ton code correspond à l'actuel.

  18. #18
    Membre éclairé
    Inscrit en
    Juin 2007
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 284
    Par défaut
    Bonjour,

    Voici les derniers résultats :

    + ça marche bien qu'on je simule le blocage avec un sleep
    + Par contre, lorsque l'instruction en question se bloque alors ça ne marche pas...en fait le prog n'arrive pas à exécuter le threadToAbort.Abort();

    Sinon,j 'ai essayé de voir l'état du thread dans les deux cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ThreadState st = threadToAbort.ThreadState;
    + cas du sleep, j'ai : Background, WaitSleepJoin
    + cas du vrai blocage, j'ai : Background

    Auriez-vous une explication svp ?

  19. #19
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Citation Envoyé par ouinih Voir le message
    + ça marche bien qu'on je simule le blocage avec un sleep
    + Par contre, lorsque l'instruction en question se bloque alors ça ne marche pas...en fait le prog n'arrive pas à exécuter le threadToAbort.Abort();
    Bonjour, je vois quelques hypothèses mais aucune ne semble correspondre, à moins que tu n'aies omis une info...
    * Le thread qu'on tente d'avorter a été suspendu. Dans ce cas, Thread.Abort() devrait lancer une exception, or tu ne dis rien de tel. La marche à suivre dans cette situation serait de tester si le thread est bien suspendu et, le cas échéant, appeler Thread.Resume() avant Thread.Abort().
    * Si Thread.Abort() a correctement été exécuté mais que l'avortement n'a pas eu lieu, c'est que l'autre thread a utilise Thread.ResetAbort(). Toutefois, dans ce cas l'exécution aurait été au-delà de la ligne Thread.Abort(), comme si celle-ci s'était exécutée normalement, mais ça ne semble pas être le cas d'après ce que tu dis. Il n'y a pas de marche à suivre dans ce cas-ci, on ne peut pas empêcher un thread d'annuler son avortement, il n'y pas d'autre solution que de tuer tout le processus.
    * Tout le processus est cramé parce que le thread qu'on tente d'avorter merdoie sévèrement. Mais tu ne serais capable de faire de l'exécution pas-à-pas dans ce cas-là.

Discussions similaires

  1. UserFunction lancer une exception?
    Par BenoitM dans le forum Développement
    Réponses: 2
    Dernier message: 23/04/2013, 10h19
  2. [PostgreSQL] Lancer un exception sur une requête échouée
    Par Nico87 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 10/07/2009, 16h05
  3. lancer une exception
    Par robert_trudel dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 25/08/2008, 21h15
  4. lancer les exceptions dans array
    Par zulad dans le forum C#
    Réponses: 8
    Dernier message: 17/07/2007, 16h22
  5. Lancer ses propres exceptions
    Par mister3957 dans le forum C++
    Réponses: 13
    Dernier message: 03/03/2007, 12h55

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