2009-04-03 6 views
1

Je possède ce code:Pourquoi ce code s'exécute-t-il plus vite que prévu?

public void replay() { 
     long previous = DateTime.Now.Ticks; 
     for (int i = 0; i < 1000; i++) { 
      Thread.Sleep(300); 
      long cur = DateTime.Now.Ticks; 
      Console.WriteLine(cur - previous); 
      previous = cur; 
     } 
    } 

qui est invoquée comme un thread séparé comme celui-ci:

 MethodInvoker replayer = new MethodInvoker(replay); 
     replayer.BeginInvoke(null, null); 

Cependant, si je regarde la sortie, il agit étrangement. Il sort i par paires. Par exemple, il attendra une attente complète, puis affichera i, puis affichera rapidement le i suivant, puis attendra de nouveau. Pourquoi fait-il cela et comment puis-je le corriger?

Il produit ceci:

3125040 
2968788 
2968788 
2968788 
3125040 
2968788 
2968788 
2968788 
3125040 
2968788 
2968788 
2968788 
3125040 

Si j'augmente le sommeil à plus d'une seconde, cela ne se produit pas.

+0

Premièrement, est-ce en mode release ou debug? Deuxièmement, utilisez une minuterie plutôt que de simplement regarder la sortie de la console - il n'y a aucune garantie que la console affichera les choses immédiatement. –

+0

il est en mode débogage – Malfist

+0

Etes-vous sûr que ce n'est pas la mise en mémoire tampon sur la console? – annakata

Répondre

7

Modifier le code pour éliminer la latence d'affichage dans votre analyse:

public void replay() 
{   
    Thread.Sleep(5000); 
    DateTime start = DateTime.Now;  
    for (int i = 0; i < 1000; i++) 
    {    
      Console.WriteLine(string.Format("Exec:{0} - {1} ms", 
       i, DateTime.Now - start)); 
      start = DateTime.Now; 
      Thread.Sleep(300);   
    } 
} 

En regardant votre sortie modifiée, il y a moins de 5% la variance (15ms sur 300) dans le délai de boucle. C'est normal, en raison des incertitudes impliquées quand le système d'exploitation assigne réellement des timeslices au thread ... (Si je me souviens bien, dans un OS de Windows, c'est normalement toutes les 20 ms!)

percevoir dans la sortie de la console est presque certainement due à l'affichage latencys.

-2

Votre sommeil dans la boucle est seulement de 300ms, ce qui n'est pas très long. Votre application doit effectuer les tâches suivantes:

  • sommeil 5 secondes
  • print 0
  • sommeil 300ms
  • imprimer 1
  • sommeil 300ms
  • imprimer 2

etc.

+0

Mais ce n'est pas le cas, et c'est le problème. – Malfist

5

Impossible de reproduire. Je me demande si c'est quelque chose de local à votre machine; tampon, peut-être.

+0

Impossible de reproduire ici non plus. – LukeH

+0

idem. Apportez le gestionnaire de tâches et surveillez vos processus. Je soupçonne que quelque chose bouffe les cycles. –

+0

suggère l'OP écrire la sortie à quelque chose d'autre - un dictionnaire peut-être - pour vérifier – annakata

2

Je ne peux pas reproduire cela, mais vous pourriez envisager une minuterie. Ce serait plus fiable.

public class Counter 
{ 
    private readonly TimeSpan initialDelay, incrementDelay; 
    private readonly int maxCount; 
    private Timer timer; 
    private int count; 

    public Counter(TimeSpan initialDelay, TimeSpan incrementDelay, int maxCount) 
    { 
     this.maxCount = maxCount; 
     this.initialDelay = initialDelay; 
     this.incrementDelay = incrementDelay; 
    } 

    public void Start(Action<int> tickBehavior) 
    { 
     if (timer != null) 
     { 
      Timer temp = timer; 
      timer = null; 
      temp.Dispose(); 
     } 
     timer = new Timer(() => 
      { 
       tickBehavior(count++); 
       if (count > maxCount) timer.Dispose(); 
      }, null, initialDelay, incrementDelay); 
    } 
} 

Utilisez-le:

Counter counter = new Counter(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(.3), 1000); 
counter.Start((count) => Console.WriteLine(count);); 

EDIT

J'utilise System.Threading.Timer, mais Counter pourrait être facilement être modifiés pour utiliser System.Timers.Timer ou System.Windows.Forms.Timer en fonction de vos besoins. Voir this link for a description de quand utiliser quelles minuteries.

+0

+1 ce morceau de code est la chose la plus cool que j'ai vue toute la semaine :) –

Questions connexes