报价不一致且波动

Ticks are inconsistent and are fluctuating

我有一个子程序和一个按钮。代码是这样的:

Private Sub plus(ByRef a As Integer)
    For i = 0 To a
        a = a + a
    Next
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim i As Integer = 19
    Dim sw As New Stopwatch
    sw.Start()
    plus(i)
    sw.Stop()
    MsgBox(sw.ElapsedTicks)
End Sub

当我运行子是通过点击"button1"程序输出310 就是说310是sw.elapsedticks

当我再次点击 "button1" 再次 运行 子时,程序输出 1 << JUST ONE ellapsedticks

怎么会这样?

我试图停止我的 vb.net 程序,我再次 运行 它,然后我再次点击它的按钮,它发生了同样的事情,这值得 272 秒表 elapsedticks 然后我再次点击stopwatch , elapsedticks 再次变为 1

请解释为什么会发生?

如果您的硬件不支持高性能计数器,StopWatch class 将退回到使用 DateTime class 并使用刻度进行测量。现在的大多数计算机,至少从 Windows 2000 年及以后,都有高性能计数器。考虑到这一点,.NET Stopwatch class 就是基于这个高频计时器的。通常,调用 Start 查询性能计数器并存储值。当您 Stop 时,它会再次查询性能计数器。然后经过的时间是这两个值的简单减法,得到你的 ElapsedTicks.

Here are a few items to have a look at for further explanation...

这个属性只是调用了GetRawElapsedTicks()

  public long ElapsedTicks { 
        get { return GetRawElapsedTicks(); }
  }

下面的函数 returns 从启动秒表到调用秒表 Stop 方法所经过的实际时间。如上所述,the elapsed time is a simple subtraction of those two values 你可以在下面看到:currentTimeStamp - startTimeStamp.

 // Get the elapsed ticks.        
#if FEATURE_NETCORE
        public long GetRawElapsedTicks() {
#else
        private long GetRawElapsedTicks() {
#endif
            long timeElapsed = elapsed;

            if( isRunning) {
                // If the StopWatch is running, add elapsed time since
                // the Stopwatch is started last time. 
                long currentTimeStamp = GetTimestamp();                 
                long elapsedUntilNow = currentTimeStamp - startTimeStamp;
                timeElapsed += elapsedUntilNow;
            }
            return timeElapsed;
        }  

您可能会注意到上面的 #if FEATURE_NETCORE 并想知道它是什么。这些被称为预处理器命令。基本上它们的工作方式类似于 if-else 语句,除了如果不满足条件,它将不会在编译时包含代码,因为它是预编译决定而不是 运行time...

综上所述,Hans Passant 已经在上面提到了即时 (JIT) 编译。我上面提到的所有这些都进一步分解以进行解释。 差异的真正原因是它编译所花费的时间,运行 第一次.

还有一件事要提。 stopwatch class 使用 long 变量类型来存储他们所谓的 frequency。 Frequency"如果存在高分辨率性能计数器的频率,则存储TicksPerSecond。频率在系统运行ning期间不能改变,所以它只是初始化一次。

下面是其他 constants,它们与频率及其计算方式有很大关系。

 private const long TicksPerMillisecond = 10000;
 private const long TicksPerSecond = TicksPerMillisecond * 1000;

当您创建 StopWatch class 的新实例时,这就是 运行。

bool succeeded = SafeNativeMethods.QueryPerformanceFrequency(out Frequency);            
            if(!succeeded) {
                IsHighResolution = false; 
                Frequency = TicksPerSecond;
                tickFrequency = 1;
            }
            else {
                IsHighResolution = true;
                tickFrequency = TicksPerSecond;
                tickFrequency /= Frequency;
            }

如您现在所见,频率在设置如何计算已用时间以及如何计算方面起着重要作用tick 通常会发生。即使您停止应用程序也没有关系,因为此时已存储频率。 重置频率的唯一方法是重新启动您的机器。