2009-04-03 12 views
1

私はこのコードを持っている:このコードはなぜ予想より速く実行されますか?

このような個別のスレッドとして起動され
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; 
     } 
    } 

:私は出力を見れば

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

しかし、それが妙に動作します。これは、ペアでiを出力します。たとえば、完全待ちを待ってからiを出力し、次のiもすばやく出力してから、もう一度待機します。なぜそれをやっているのですか?それをどうやって修正できますか?

それは、この出力:

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

私はこれが起こらない秒以上に睡眠を増やす場合。

+0

まず、リリースモードまたはデバッグモードですか?次に、コンソールの出力を監視するのではなく、タイマーを使用してください。コンソールにすぐに表示されるという保証はありません。 –

+0

これはデバッグモードです – Malfist

+0

これはコンソールでバッファリングされていませんか? – annakata

答えて

7

変更、分析の表示待ち時間を排除するためにコード:あなたの修正された出力を見て

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);   
    } 
} 

、ループ遅延で5%未満の変動(300のうち15ミリ秒)があります。これは通常、OSが実際にスレッドにタイムスライスを割り当てるときの不確実性のために正常です...(Windows OSで正しくリコールすると、これは通常20 msごとです)

大きな矛盾コンソールの出力を知覚することは、ほぼ確実にlatencysを表示することによるものです。

-2

ループ内の睡眠はわずか300msで、あまり長くありません。あなたのアプリケーションには、次の操作を行います:

  • スリープ5秒
  • 印刷0
  • スリープ300msの
  • プリント1
  • スリープ300msの
  • プリント2

など

+0

しかし、それは問題ではありません。 – Malfist

5

再現できません。私はそれがあなたのマシンにとってローカルなものかどうか疑問に思います。おそらく、バッファリング。

+0

ここでは再現できません。 – LukeH

+0

。タスクマネージャを起動し、プロセスを監視します。私は何かがサイクルを食べていると思う。 –

+0

は、OPが何かに出力を書き出すことを示唆しています - 辞書おそらく - ダブルチェック – annakata

2

私はこれを再現できませんが、タイマーを考慮する必要があります。それはより信頼できるでしょう。

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); 
    } 
} 

それを使用します。

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

EDIT

を私はSystem.Threading.Timerを使用していますが、Counterは簡単にあなたの必要性に応じて、System.Timers.TimerSystem.Windows.Forms.Timerを使用するように変更することができます。どのタイマーを使用するかについては、this link for a descriptionを参照してください。

+0

+1そのコードは一週間で見た中で最もクールなものです:) –

関連する問題