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 :

VB et les exceptions


Sujet :

VB.NET

  1. #1
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mars 2011
    Messages : 43
    Par défaut VB et les exceptions
    bonjour
    j'ai créé une fonction CBstatus() en VB.net et un timer qui fais l'appel à cette fonction chaque 10 ms
    cette fonction permet de recupérer des donné sur un bus CAN ,donc s'il ya pas donné elle présente un erreur que je dois l’afficher une seul fois ,c'est pour cela j'ai mé une condition if pour afficher ce meessage une seul fois mais malheuresemnt ca marche pas tjr il me donne des fenêtre d'erreur suivant le timer
    voila le code et merci pour une idée

    Code Visual Basic :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    dim i as integer =0
     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
     
     
    try 
    CBstatus()
    Catch ex As Exception
     
     if i=0 then
        msgbox(" pas de donné sur le bus CAN")
        i=1
    end if
    End Try
    End Sub

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    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 198
    Par défaut
    à tout hasard met i à 1 avant le msgbox, des fois qu'il soit bloquant (mais je ne pense pas)

    sinon est-ce un timer trouvé dans la boite à outils ou un timer autre (et donc pas system.windows.forms.timer)

    par contre en général pour des choses où l'état de connexion peut changer dans le temps je pense qu'il est préférable de l'afficher visuellement sur le form (rond vert/rouge par exemple ou encore label visible/invisible)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Inactif
    Homme Profil pro
    Auteur logiciels et romans
    Inscrit en
    Février 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Auteur logiciels et romans
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2009
    Messages : 203
    Par défaut réponse : abdobergach
    Citation Envoyé par abdobergach Voir le message
    bonjour
    j'ai créé une fonction CBstatus() en VB.net et un timer qui fais l'appel à cette fonction chaque 10 ms
    cette fonction permet de recupérer des donné sur un bus CAN ,donc s'il ya pas donné elle présente un erreur que je dois l’afficher une seul fois ,c'est pour cela j'ai mé une condition if pour afficher ce meessage une seul fois mais malheuresemnt ca marche pas tjr il me donne des fenêtre d'erreur suivant le timer
    voila le code et merci pour une idée

    Code Visual Basic :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    dim i as integer =0
     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
     try 
      CBstatus()
      Catch ex As Exception
       if i=0 then
         msgbox(" pas de donné sur le bus CAN")
         i=1
       end if
     End Try
    End Sub
    Bonjour,

    A priori ça semble tourner rond ... question subsidiaire, le i ne serait pas modifié ailleurs ?

    Peux-tu essayer d'englober le try par un if ou un select case (sur i) ?

    Sinon, le timer à 10 ms, moi en vb6 j'avais testé, et en dessous de 50 ms ce n'est pas significatif, il n'a pas le temps de faire son travail (lire le code, empiler, passer au processeur, exécuter, puis le retour), plus l'état du processeur selon les tâches de fond de l'OS (qui tourne toutes seules comme des grandes), je doute qu'en 10 ms il fasse ça, donc... il y a peut être une sorte de bourrage qui se crée et sature la fonction, j'ai déjà vu ça, alors sans aller jusqu'à planter il prend du retard et débloque un peu ?

    Moi je mettrais le timer à 50 ms et je le soulagerais avec devant le try un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    My.Application.DoEvents()

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    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 198
    Par défaut
    Citation Envoyé par Ehjoe Voir le message
    Sinon, le timer à 10 ms, moi en vb6 j'avais testé, et en dessous de 50 ms ce n'est pas significatif, il n'a pas le temps de faire son travail (lire le code, empiler, passer au processeur, exécuter, puis le retour), plus l'état du processeur selon les tâches de fond de l'OS (qui tourne toutes seules comme des grandes), je doute qu'en 10 ms il fasse ça, donc... il y a peut être une sorte de bourrage qui se crée et sature la fonction, j'ai déjà vu ça, alors sans aller jusqu'à planter il prend du retard et débloque un peu ?
    c'est vrai qu'il n'y aucune différence entre vb6 et vb.net et que les pcs n'ont pas évolué depuis 15 ans
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  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
    Aucun rapport avec VB6 et VB.Net ou l'évolution des machines.

    Les timers de base de VB6 comme de DotNet, DateTime.Now, Thread.Sleep, les WaitEventHandle et leurs frangins non-managés, etc... reposent tous au moins indirectement sur des messages WM_TIMER, des messages Win32 traités avec une basse priorité. Tous les timers basés sur ce mécanisme ont une résolution grossière (15.6ms -> 64Hz).

    Si on veut dépasser le problème, deux solutions :
    * On peut améliorer la résolution de WM_TIMER avec timeBeginPeriod, jusqu'à 1ms je crois. Mais le thread peut néanmoins dormir quand le tic débarque, auquel cas il ne sera traité qu'au réveil, voir ci-dessous.
    * On peut utiliser QueryPerformanceCounter via StopWatch (précision de l'ordre de la microseconde) pour obtenir des mesures temporelles précises avec un thread tournant en continu sans jamais dormir. Problème : même avec la plus haute priorité, je crois que Windows peut mettre un thread en pause jusqu'à plusieurs dizaines de millisecondes pour permettre le traitement des autres threads.
    * Enfin, on peut aller lorgner vers les solutions temps réel : créer un thread système (PsCreateSystemThread) et l'associer à certaines interruptions système pour forcer Windows à réveiller le thread à chaque tic. On atteint là une résolution de l'ordre d'une centaine de microsecondes il me semble. Il existe des biblios (Real Time Module) pour simplifier ça et portables entre OS.

  6. #6
    Inactif
    Homme Profil pro
    Auteur logiciels et romans
    Inscrit en
    Février 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Auteur logiciels et romans
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2009
    Messages : 203
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    c'est vrai qu'il n'y aucune différence entre vb6 et vb.net et que les pcs n'ont pas évolué depuis 15 ans
    Bonjour le cerf,

    Mais non, je parle de maintenant moi, mais tout le monde sait, s'il à l'habitude de VB, qu'on ne descend pas en dessous de 50 ms, et encore...

  7. #7
    Inactif
    Homme Profil pro
    Auteur logiciels et romans
    Inscrit en
    Février 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Auteur logiciels et romans
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2009
    Messages : 203
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    Aucun rapport avec VB6 et VB.Net ou l'évolution des machines.

    Les timers de base de VB6 comme de DotNet, DateTime.Now, etc... reposent tous au moins indirectement sur des messages WM_TIMER, des messages Win32 traités avec une basse priorité. Tous les timers basés sur ce mécanisme one une résolution grossière (15.6ms -> 64Hz).

    Pour avoir des mesures temporelles précises il faut passer par QueryPerformanceCounter. C'est ce que fait Stopwatch, introduit dans la version 2.0 de dotnet. Cela dit, ici, je ne sais pas trop quoi faire, je ne sais pas s'il existe un timer capable de réveiller un thread avec de courts intervalles entre deux réveils..

    EDIT : dernier paragraphe supprimé, j'ai écrit une bourde, afk google.

    Bonsoir Donquich,

    Sais-tu ce que fais ce code ? Il doit être lu, puis effectuer les tests, puis empiler les adresses, puis passer au processeur, exécuter l'ordre (qui pend aussi du temps), puis revenir, plus le temps où le processeur est occupé par des taches de fond, puis retourner le pointeur d'où il est parti en dépilant, tant est qu'il ne faille pas un accès disque (env 10 ms), et tu crois que ceci se fait en 10 ms ?

    Ben moi je n'ai jamais rien eu de significatif en dessous de 50 ms, mais je dirais plutôt 100 à 200, car il n'y a pas que la mémoire là, il y a le code à lire, à exécuter, des accès disque parfois, ça prend tu temps tout ça !

    Rien qu'un "IF" dans le code sur une séquence d'une minute, tu pourras voir la différence à l'oeil.

    Citation Envoyé par DonQuiche Voir le message
    Aucun rapport avec VB6 et VB.Net ou l'évolution des machines.

    Les timers de base de VB6 comme de DotNet, DateTime.Now, etc... reposent tous au moins indirectement sur des messages WM_TIMER, des messages Win32 traités avec une basse priorité. Tous les timers basés sur ce mécanisme one une résolution grossière (15.6ms -> 64Hz).

    Pour avoir des mesures temporelles précises il faut passer par QueryPerformanceCounter. C'est ce que fait Stopwatch, introduit dans la version 2.0 de dotnet. Cela dit, ici, je ne sais pas trop quoi faire, je ne sais pas s'il existe un timer capable de réveiller un thread avec de courts intervalles entre deux réveils..

    EDIT : dernier paragraphe supprimé, j'ai écrit une bourde, afk google.

    Suite:

    Tu peux déjà faire ça pour avoir une idée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    button1_click...
    dim i as integer
    dim t(2) as string
    t(1001) = tempsMachien
    for i = 1 to 1000
      t(i)=tempsMachine
    next i
    t(1001)=tempsMachine
     
    ' Puis tu fais 
    msgbox ((t(1001) - t(0)) / 1000)
    ' et tu auras une idée à vide de la vitesse, mais à vide, si tu mets un peu 
    ' de code dans ta boucle c'est plus pareil.
    Alors, tu trouves combien ?

  8. #8
    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
    Bonsoir Ehjoe.

    En fait, même si ton code d'exécutait instantanément, il pourrait quand même y avoir un problème avec Timer_Tick. C'est simplement que les tics sont programmés pour arriver toutes les 15,6 ms (même si tu as mis 10ms) et qu'il pourrait en fait s'écouler beaucoup plus de temps entre deux tics. Par exemple, si la machine est occupée, il pourrait se dérouler 50 ou 100ms. Ainsi, la séquence suivante poserait-elle un problème pour ton application (je considère que les tics arrivent toutes les 10ms même si c'est faux) ?
    * 0ms : Timer1_Tick trouve desdonnées dans le bus -> traitement
    * 10ms : aucune nouvelle donnée dans le bus mais le thread est endormi. -> pas d'erreur notifiée alors qu'il aurait fallu.
    * 15ms : réception de données dans le bus.
    * 35ms : le thread est réveillé et reçoit trois Timer1_Tick (10ms, 20ms, 30ms). Le premier découvre des données dans le bus -> traitement

    Ensuite, si tu es certain que ton traitement prend plus de 10ms et que le cas normal et qu'il y ait des données à traiter, l'utilisation d'un timer n'est pas le choix le plus judicieux : sitôt un tic traité, tu vas recevoir tous les tics non-traités d'un coup. Au final, tu entasseras des tics en attente et je ne sais pas très bien sur quoi ça va déboucher (Windows croira t-il que l'application ne répond pas ?) Avec un traitement de 51ms et un thread mono-timer (windows forms par exemple), tu vas avoir la séquence suivante (je considère que les tics arrivent toutes les 10ms même si c'est faux).
    * 0ms: Timer1_Tick commence
    * 10ms: tic retardé, le thread est occupé, 1 tic en attente.
    * 20ms: tic retardé, le thread est occupé, 2 tics en attente.
    * 30ms: tic retardé, le thread est occupé, 3 tics en attente.
    * 40ms: tic retardé, le thread est occupé, 4 tics en attente.
    * 50ms: tic retardé, le thread est occupé, 5 tics en attente.
    * 51ms: traitement terminé, début du traitement du tic notifié à t=10ms. 4 tics restant en attente.
    * 60ms: tic retardé, le thread est occupé, 5 tics en attente.

    Si tu utiliser un timer du type System.Threading.Timer, qui opère sur tous les threads du ThreadPool (16 par défaut), tu vas avoir cinq traitements en parallèle en moyenne, et jusqu'à 16 simultanément après un réveil du thread.

    Du coup, il semblerait plus judicieux d'avoir recours au polling : un simple thread avec un code comme celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    bool error = false;
    while(true)
    {
       if (DonneesDansLeBus()) Traitement()
       else
       {
           error = true;
           break;
       }
    }
     
    if (error) msg("erreur");
    Evidemment, si tu dois absolument signaler une erreur dans le cas où aucune donnée n'est présentée au bus dans un intervalle de dix secondes, ce code échouera lui aussi dans certains cas, s'il est endormi à ce moment. Il échouera aussi si ton traitement est finalement plus rapide que dix secondes, il faudra utiliser StopWatch pour vérifier le temps écoulé depuis le dernier relevé avant de signaler une erreur.

    PS : La boucle de 1 à 1000 que tu proposes s'éxécuterait en à 1 à 10ns (nanoseconde, milliardième de seconde) si elle était vide et, comme je l'ai expliqué, le plus précis des timers n'a qu'une précision d'une micro-seconde, on ne peut donc pas mesurer une telle durée. Qui plus est, dans le boucle que tu proposais, c'est la lecture du temps machine qui prendrait du temps, et non l'itération/vérification de la boucle.

  9. #9
    Inactif
    Homme Profil pro
    Auteur logiciels et romans
    Inscrit en
    Février 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Auteur logiciels et romans
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2009
    Messages : 203
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    Bonsoir Ehjoe.

    En fait, même si ton code d'exécutait instantanément, il pourrait quand même y avoir un problème avec Timer_Tick. C'est simplement que les tics sont programmés pour arriver toutes les 15,6 ms (même si tu as mis 10ms) et qu'il pourrait en fait s'écouler beaucoup plus de temps entre deux tics. Par exemple, si la machine est occupée, il pourrait se dérouler 50 ou 100ms. Ainsi, la séquence suivante poserait-elle un problème pour ton application ?
    * 0ms : Timer1_Tick trouve desdonnées dans le bus -> traitement
    * 10ms : aucune nouvelle donnée dans le bus mais le thread est endormi. -> pas d'erreur notifiée alors qu'il aurait fallu.
    * 15ms : réception de données dans le bus.
    * 35ms : le thread est réveillé et reçoit trois Timer1_Tick (10ms, 20ms, 30ms). Le premier découvre des données dans le bus -> traitement

    Ensuite, si tu es certain que ton traitement prend plus de 10ms et que le cas normal et qu'il y ait des données à traiter, l'utilisation d'un timer n'est pas le choix le plus judicieux : sitôt un tic traité, tu vas recevoir tous les tics non-traités d'un coup. Au final, tu entasseras des tics en attente et je ne sais pas très bien sur quoi ça va déboucher (Windows croira t-il que l'application ne répond pas ?) Avec un traitement de 51ms et un thread mono-timer (windows forms par exemple), tu vas avoir la séquence suivante.
    * 0ms: Timer1_Tick commence
    * 10ms: tic retardé, le thread est occupé, 1 tic en attente.
    * 20ms: tic retardé, le thread est occupé, 2 tics en attente.
    * 30ms: tic retardé, le thread est occupé, 3 tics en attente.
    * 40ms: tic retardé, le thread est occupé, 4 tics en attente.
    * 50ms: tic retardé, le thread est occupé, 5 tics en attente.
    * 51ms: traitement terminé, début du traitement du tic notifié à t=10ms. 4 tics restant en attente.
    * 60ms: tic retardé, le thread est occupé, 5 tics en attente.

    Si tu utiliser un timer du type System.Threading.Timer, qui opère sur tous les threads du ThreadPool (16 par défaut), tu vas avoir cinq traitements en parallèle en moyenne, et jusqu'à 16 simultanément après un réveil du thread.

    Du coup, il semblerait plus judicieux d'avoir recours au polling : un simple thread avec un code comme celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    bool error = false;
    while(true)
    {
       if (DonneesDansLeBus()) Traitement()
       else
       {
           error = true;
           break;
       }
    }
     
    if (error) msg("erreur");
    Evidemment, si tu dois absolument signaler une erreur dans le cas où aucune donnée n'est présentée au bus dans un intervalle de dix secondes, ce code échouera lui aussi dans certains cas, s'il est endormi à ce moment. Il échouera aussi si ton traitement est finalement plus rapide que dix secondes, il faudra utiliser StopWatch pour vérifier le temps écoulé depuis le dernier relevé avant de signaler une erreur.

    PS : La boucle de 1 à 1000 que tu proposes s'éxécuterait en à 1 à 10ns (nanoseconde, milliardième de seconde) si elle était vide et, comme je l'ai expliqué, le plus précis des timers n'a qu'une précision d'une micro-seconde, on ne peut donc pas mesurer une telle durée. Qui plus est, dans le boucle que tu proposais, c'est la lecture du temps machine qui prendrait du temps, et non l'itération/vérification de la boucle.

    Bonsoir bis, DonQuich,

    Tiens j'ai fait ça :

    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
     
    Option Explicit On
    Public Class Form1
      Dim t(1001) As Long
      Dim avance As Integer
     
      Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Interval = 10
        Timer1.Enabled = False
      End Sub
     
      Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        avance = 0
        t(avance) = My.Computer.Clock.TickCount
        Timer1.Enabled = True
      End Sub
     
      Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If avance > 1000 Then
          t(1001) = My.Computer.Clock.TickCount
          Timer1.Enabled = False
          Call fin()
        End If
        t(avance) = My.Computer.Clock.TickCount
        avance = avance + 1
      End Sub
     
      Sub fin()
        Dim j As Integer
        ListBox1.Items.Clear()
        For j = 0 To 1001
          ListBox1.Items.Add(t(j))
        Next j
        MsgBox((t(1001) - t(0)) / 1000) ' 15,772
      End Sub
    End Class
    Et je trouve pour un timer à 10 (15,772 ms), et encore, il ne fait là aucun boulot externe, ni comparaison (TRY), ni comparaison (IF dans TRY), voir origine question qui n'est pas de moi.
    Il ne sort pas de sa procédure... sinon ce serait bien davantage, c'est pourquoi je disais qu'un timer au minimim c'est 50 ms pour laisser temps au job de se faire.

    Je dirais même mieux, pour bien régler un timer à optimiser, faut compter le temps du travail en entrée et sortie, le diviser par le nombre de passe et ensuite régler le timer avec une petite marge sur le résultat...

  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
    Avant toute chose, désolé à tous deux de vous avoir confondus, abdobergach et Ehjoe.

    Pour revenir au code que tu as posté, Ehjoe, le résultat était tout à fait prévisible mais tu l'interprètes d'une façon erronée. Tu considères que si 15ms se sont écoulées entre chaque appel tic du timer, c'est parce que Windows était trop occupé. C'est faux, entre deux tics de timer, l'activité cumulée du système d'exploitation, de toutes les tâches de fond, les appels à l'infrastructure derrière le Timer, etc... est en moyenne de quelques microsecondes. Et encore...

    La raison pour laquelle deux tics se produisent à 15.6ms d'intervale, c'est parce que les messages WM_TIMER dont dépend ton timer ne sont envoyés que 64 fois par seconde. Pour faire simple, le système d'explioitation s'est enregistré sur le PIT (programmable interrupt timer) du Northbridge, une sorte de timer système de l'architecture de nos PC. Il l'a fait en demandant une fréquence de 64Hz (1000 / 64 = 15.6). Toutes les 15.6 ms, une fonction de ce genre est donc réveillée par le système :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Ce code système se produit toutes les 15.6ms
    void pit_tick(...)
    {
        // Met à jour l'horloge interne système (dont dépend My.Computer.Clock.TickCount)
        // Réveille les threads dont la durée de sommeil a expiré
        // Réactive les primitives de synchronisation qui ont atteint la durée maximale d'attente sans recevoir de signaux.
        // Envoie les messages WM_TIMER aux applications ayant des timers dont les intervalles ont été dépassés.
    }
    C'est la raison pour laquelle une boucle while comme que celle de ton code précédent renvoie une durée écoulée de 0 : la boucle s'est terminée avant que le prochain pit_tick ne se produise et que My.Computer.Clock.TickCount ne soit mis à jour. Et c'est la raison pour laquelle, dans ton dernier exemple, tes tics se produisent toutes les 15.6ms plutôt que toutes les 10ms. Si tu avais spécifié 20ms d'intervalle, certains tics se seraient suivis à 15.6ms d'intervalle, d'autres à 31.2 (15.6 * 2) ms d'intervalle. Au final, sur 20s, tu aurais reçu 1000 tics.


    De nos jours, on pourrait bien sûr demander un plus faible intervalle. Mais cette fréquence date des débuts de Windows et, à l'époque, c'était une bien haute fréquence. Dans la mesure où certains applications reposent sur l'hypothèse d'une fréquence de 64Hz du timer système, changer cette valeur pourrait provoquer des dysfonctionnements. A défaut, Windows propose des API pour ceux qui ont besoin d'une plus haute résolution.

    PS : NT acceptait dans le boot.ini un paramètre pour améliorer la résolution du timer système : "/TIMERES=number" où number est un multiple de 100ns. Je présume que ce paramètre fonctionne toujours. Si tu mets une valeur de 1 ou 10, tu verras que tes tics se produiront bien à 10ms d'intervalle.
    PPS : Sous Linux, la fréquence par défaut est de 250Hz je crois (4ms d'intervalle).

  11. #11
    Inactif
    Homme Profil pro
    Auteur logiciels et romans
    Inscrit en
    Février 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Auteur logiciels et romans
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2009
    Messages : 203
    Par défaut
    Citation Envoyé par DonQuiche Voir le message
    Avant toute chose, désolé à tous deux de vous avoir confondus, abdobergach et Ehjoe.
    Cher ami DonQuiche,

    Je ne comprends pas tout, si tes tiks se produisent à 15 ms, régler le timer à 10 serai inutile, non, ce serait un minimum de 15 ?

    Tout ça est théorique car on part du principe qu'entre deux tour le timer ne fait pas grand chose, mais dans la pratique, souvent il va aller traiter une fonction cossue puis afficher le résultat en liste, et là à 10 ms il ne suivra pas, ne pourra exécuter le code que tous lesn 3 pou 4 ticks...

    Par contre si tu fais un programme de course qui écrit seulement en mémoire, et qu'uniquement à l'arrêt du timer il reverse la mémoire dans une liste par exemple, là oui, puisque la RAM tourne dans les 80 ns, en fait, ça dépend ce de qu'on fait.

    Mais pour le cas de notre ami, qui poste un peu partout (sauf chez MS), ben une des cause de son déraillement peut être que le timer prend sans cesse du retard, car ce qu'il a à faire ne peut se faire en 10 ms (15 ms), alors déjà l'exécution sera irrégulière, mais en plus ça va bourrer au bout d'un moment, la vitesse d'exécution sera loin de celle demandée au timer, non ?

    Parce que si j'ai compris, il tick tous les 15 ms, et si quand il arrive il n'est pas désiré, il refait une balade et revient 15 ms plus tard, ce qui correspond bien à ce que je dis, à savoir qu'il faut faire et mesurer un traitement sans timer afin ensuite de pouvoir donner au timer un rapidité compatible avec ce qu'il a à faire entre deux passage, non ?

    Je trouve 15,772 ms, mais si je lui fais remplir une listBox visible de 60.000 datas, je crois bien que le tick de 15 ms, il va en sauter beaucoup, et on aura une réalisation par exemple de 80 ms par boucle timer, soit tous les 8 ticks, non ?

  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
    Je vais tenter de te répondre point par point :
    * Régler le timer à un intervalle inférieur à 15.6ms ne sert à rien en effet. Ou plutôt, ça sert à être sûr que l'on aura un tic toutes les 15.6ms. 1ms, 10ms, ou 15.6ms, c'est la même chose. En tout cas c'est vrai sur un Windows standard pour lequel on n'a pas spécifié une résolution accrue du timer.

    * Il est possible que le code appelé dure plus de 15ms, en effet. Cela dit, il faut quand même y aller pour occuper le CPU pendant 15ms avec un code compilé. Mais si des actions UI ou des accès disques sont impliqués, pourquoi pas.

    * Si donc le code prend plus de 15ms à s'exécuter (mettons 50ms), le résultat dépendra du timer. J'avais détaillé ce cas précédemment : avec le timer de WindowsForms, les tics seront traités les uns à la suite des autres à 50ms d'intervalle. Avec un timer threading, on va finir avec 16 threads bossant en même temps sur autant de tics, démarrant à des intervalles aléatoires (de 1ms à 800ms) et le résultat est imprévisible : ça pourrait être une des causes mais le message original est vague quant au problème constaté ; qui plus est je ne sais pas si msgbox est thread-safe, sinon son appel lèverait une exception. Enfin, dans les deux cas le bourrage de la file d'attente des messages risque de provoquer un crash de l'application à long terme je pense (Windows a détecté que l'application ne répond pas), pas sûr.

    * Si le code prend plus de 15ms à s'exécuter, la bonne solution ici est donc, comme je l'ai expliqué plus haut, d'utiliser un thread poller plutôt qu'un timer. Chronométrer la durée ne serait pas la bonne approche car cette durée peut varier selon la machine et son utilisation. Or, le code doit être résilient et capable de s'adapter à toute situation.

    * Si le code est rapide en général et lent dans quelques cas rares, on peut conserver un timer un balancer sur un thread distinct le traitement long.

    * Enfin, d'autres causes possibles de bug sont, comme je l'avais mentionné, des tics retardés (plus de 15ms entre deux tics) parce que le thread est mis en sommeil par Windows pour laisser d'autres threads s'exécuter.

  13. #13
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 198
    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 198
    Par défaut
    de toute facon un timer ne sert pas à faire un gros traitement, mais à faire clignoter un truc ou changer le texte d'un label, et donc le timing est de l'ordre de l'humain, genre 500ms

    pour faire un traitement on utilise un thread qui permet beaucoup plus de précision
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. [Exception]Comment gérer les exceptions ?
    Par Gildas Huart dans le forum Général Java
    Réponses: 7
    Dernier message: 29/03/2005, 18h01
  2. imprimer les exception
    Par deeal dans le forum Général Python
    Réponses: 2
    Dernier message: 05/01/2005, 16h16
  3. Utiliser les exceptions pour un traitement particulier ?
    Par Blustuff dans le forum Assembleur
    Réponses: 11
    Dernier message: 01/12/2004, 02h21
  4. [Exceptions] Pb avec les exceptions
    Par joquetino dans le forum Langage
    Réponses: 11
    Dernier message: 22/09/2004, 17h08
  5. Intercepter les 'Exceptions'
    Par Teo dans le forum ASP
    Réponses: 3
    Dernier message: 05/01/2004, 19h55

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