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

スリープを 1 秒以上に増やしても、これは起こりません。

4

4 に答える 4

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のうち15ms)です。OSが実際にスレッドにタイムスライスを割り当てるときに関係する不確実性のため、これは正常です...(正しく思い出せば、Windows OSでは、これは通常20ミリ秒ごとです!)

コンソール出力で認識される大きな不一致は、ほぼ確実に表示の遅延によるものです。

于 2009-04-03T14:58:24.037 に答える
5

再現できません。それはあなたのマシンにローカルなものなのだろうか。おそらくバッファリング。

于 2009-04-03T14:52:34.563 に答える
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););

編集

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

于 2009-04-03T15:04:56.873 に答える
-2

ループ内のスリープはわずか 300 ミリ秒で、それほど長くはありません。アプリケーションは次のことを行います。

  • 5秒眠る
  • 印刷 0
  • スリープ 300ms
  • 印刷 1
  • スリープ 300ms
  • 印刷 2

于 2009-04-03T14:52:17.933 に答える