我有这段代码:
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 :(得分: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)。这是正常的,因为操作系统实际上将时间片分配给线程时所涉及的不确定性......(如果我没记错,在Windows操作系统中,这通常只需要每20毫秒!)
您在控制台输出中感知的较大差异几乎可以肯定是由于显示器延迟。
答案 1 :(得分:5)
无法重现。我想知道它是否是你机器本地的东西;或许缓冲。
答案 2 :(得分: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.Timer
或System.Windows.Forms.Timer
。请参阅this link for a description何时使用哪个计时器。
答案 3 :(得分:-2)
你在循环内的睡眠只有300毫秒,这不是很长。您的应用程序将执行以下操作:
等