.NET System.Diagnostics.Stopwatch问题(返回值过低) [英] .NET System.Diagnostics.Stopwatch issue (returns values too low)

查看:173
本文介绍了.NET System.Diagnostics.Stopwatch问题(返回值过低)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的电脑秒表正在返回太低值。例如,200毫秒时,我指定的 Thread.sleep代码(1000)。该计划应该等待1秒。我还测试了 ManualResetEvent.WaitOne(1000)并得到了相同的结果。这两个框架2.0和3.0给出了这样奇怪的行为。我运行Windows XP SP3与.NET Framework 3.5 SP1中。

下面是我的测试(以下code)的结果是:

  1000毫秒DateTime.Now.Ticks
0201毫秒Stopwatch.ElapsedTicks
0142毫秒Stopwatch.ElapsedMilliseconds
0139毫秒复位后Stopwatch.ElapsedTicks
0264毫秒Stopwatch.ElapsedTicks设置ThreadAffinity
0151毫秒Stopwatch.ElapsedTicks设置ProcessorAffinity(及以上)
0371毫秒Stopwatch.ElapsedTicks与Syncronized对象
完成!
 

// Program.cs的文件

 类节目
{
    静态无效的主要(字串[] args)
    {
        StopWatchTest.Go();
        Console.WriteLine(完成!);
        到Console.ReadLine();
    }
}
 

// StopWatchTest.cs类

 内部静态类StopWatchTest
{
    公共const int的睡眠时间= 1000;

    公共静态无效围棋()
    {
        #区域试验#0与DateTime.Now.Ticks
        长startTick = DateTime.Now.Ticks;
        Thread.sleep代码(睡眠时间);
        长stopTick = DateTime.Now.Ticks;
        长ela​​psedDt =(stopTick  -  startTick)* 100;
        显示器((int)的(elapsedDt / 1000/1000),DateTime.Now.Ticks);
        #endregion测试#0与DateTime.Now.Ticks

        秒表手表= Stopwatch.StartNew();
        长频率= Stopwatch.Frequency;
        双nanosecPerTick =(1000.0 * 1000.0 * 1000.0)/频率;

        #区域试验#1 Stopwatch.ElapsedTicks
        startTick = watch.ElapsedTicks;
        Thread.sleep代码(睡眠时间);
        stopTick = watch.ElapsedTicks;
        双elapsedSw =(stopTick  -  startTick)* nanosecPerTick;
        显示器((int)的(elapsedSw / 1000/1000),Stopwatch.ElapsedTicks);
        #endregion测试#1 Stopwatch.ElapsedTicks

        #区域试验#2 Stopwatch.ElapsedMilliseconds
        startTick = watch.ElapsedMilliseconds;
        Thread.sleep代码(睡眠时间);
        stopTick = watch.ElapsedMilliseconds;
        显示器((int)的(stopTick  -  startTick),Stopwatch.ElapsedMilliseconds);
        #endregion测试#2 Stopwatch.ElapsedMilliseconds

        #地区测试#3与复位后Stopwatch.ElapsedTicks
        watch.Stop();
        watch.Reset();
        watch.Start();
        startTick = watch.ElapsedTicks;
        Thread.sleep代码(睡眠时间);
        stopTick = watch.ElapsedTicks;
        elapsedSw =(stopTick  -  startTick)* nanosecPerTick;
        显示((INT)(elapsedSw / 1000/1000),复位后Stopwatch.ElapsedTicks);
        #endregion测试#3与复位后Stopwatch.ElapsedTicks

        #区域试验#4 Stopwatch.ElapsedTicks和ThreadAffinity
        Thread.BeginThreadAffinity();
        startTick = watch.ElapsedTicks;
        Thread.sleep代码(睡眠时间);
        stopTick = watch.ElapsedTicks;
        elapsedSw =(stopTick  -  startTick)* nanosecPerTick;
        显示器((int)的(elapsedSw / 1000/1000),Stopwatch.ElapsedTicks设置ThreadAffinity);
        Thread.EndThreadAffinity();
        #endregion测试#4 Stopwatch.ElapsedTicks和ThreadAffinity

        #区域试验#5与Stopwatch.ElapsedTicks和ProcessorAffinity(及以上)
        const int的亲和力= 0×0001;
        过程PROC = Process.GetCurrentProcess();
        proc.ProcessorAffinity =新的IntPtr(亲和);
        proc.PriorityClass = ProcessPriorityClass.High;
        ProcessThreadCollection PTC = proc.Threads;
        的foreach(ProcessThread PT在PTC)
        {
            pt.IdealProcessor ​​= 0;
            pt.ProcessorAffinity =新的IntPtr(亲和);
        }
        Thread.CurrentThread.Priority = ThreadPriority.Highest;

        startTick = watch.ElapsedTicks;
        Thread.sleep代码(睡眠时间);
        stopTick = watch.ElapsedTicks;
        elapsedSw =(stopTick  -  startTick)* nanosecPerTick;
        显示器((int)的(elapsedSw / 1000/1000),Stopwatch.ElapsedTicks设定ProcessorAffinity(和更多));
        #endregion测试#5与ProcessorAffinity多

        #区域试验#6 Syncronized对象
        。elapsedSw =新SyncTimer()走();
        显示器((int)的(elapsedSw / 1000/1000),用Stopwatch.ElapsedTicks Syncronized对象);
        #endregion试验#6 Syncronized对象
    }

    私有静态无效显示器(INT毫秒,串测试名称)
    {
        Console.WriteLine({0:0000}毫秒{1},单位为毫秒,测试名);
    }
}

[同步​​]
内部类SyncTimer:ContextBoundObject
{
    [MethodImpl(MethodImplOptions.Synchronized)
    公共双围棋()
    {
        Stopwatch.StartNew();
        长频率= Stopwatch.Frequency;
        双nanosecPerTick =(1000.0 * 1000.0 * 1000.0)/频率;

        长startTick = Stopwatch.GetTimestamp();
        Thread.sleep代码(StopWatchTest.SleepTime);
        长stopTick = Stopwatch.GetTimestamp();
        返回(stopTick  -  startTick)* nanosecPerTick;
    }
}
 

解决方案

看一看下面的链接:

<一个href="https://connect.microsoft.com/VisualStudio/feedback/details/94083/stopwatch-returns-negative-elapsed-time">https://connect.microsoft.com/VisualStudio/feedback/details/94083/stopwatch-returns-negative-elapsed-time

<一个href="http://stackoverflow.com/questions/1008345/system-diagnostics-stopwatch-returns-negative-numbers-in-elapsed-properties">System.Diagnostics.Stopwatch返回负数的消逝......性能

这似乎有一个问题,秒表精确度可导致其返回负的运行时间,同时也广泛不同的时间。如果你看一下连接的问题,大多数人也都在谈论看到的虚拟机,这就是我们所看到的负面消逝值问题的问题。

纵观 QueryPerformanceCounter的文档,这似乎在暗示这问题可能发生在多处理器系统由于BIOS或硬件抽象层的错误,但没有给出进一步的信息,而不是具体的关于虚拟机。

对于解决这个问题...我还没有找到一个在很多使用Google。可以忽略的值小于零,这是不理想的,但可行的情况。但是,这并不解决您的问题 - 你怎么知道什么样的价值观是无效的。

希望这有助于一些。

On my computer the Stopwatch is returning values way too low. For example, 200 ms when I specified Thread.Sleep(1000). The program is supposed to wait 1 second. I also tested with ManualResetEvent.WaitOne(1000) and got the same results. Both framework 2.0 and 3.0 gives this strange behavior. I am running Windows XP SP3 with .NET Framework 3.5 SP1.

Here is the result of my tests (code below):

1000 ms for DateTime.Now.Ticks
0201 ms for Stopwatch.ElapsedTicks
0142 ms for Stopwatch.ElapsedMilliseconds
0139 ms for Stopwatch.ElapsedTicks after Reset
0264 ms for Stopwatch.ElapsedTicks setting ThreadAffinity
0151 ms for Stopwatch.ElapsedTicks setting ProcessorAffinity (and more)
0371 ms for Stopwatch.ElapsedTicks with Syncronized object
Done!

// Program.cs file

class Program
{
    static void Main(string[] args)
    {
        StopWatchTest.Go();
        Console.WriteLine("Done!");
        Console.ReadLine();
    }
}

// StopWatchTest.cs class

internal static class StopWatchTest
{
    public const int SleepTime = 1000;

    public static void Go()
    {
        #region Test #0 with DateTime.Now.Ticks
        long startTick = DateTime.Now.Ticks;
        Thread.Sleep(SleepTime);
        long stopTick = DateTime.Now.Ticks;
        long elapsedDt = (stopTick - startTick) * 100;
        Display((int)(elapsedDt / 1000 / 1000), "DateTime.Now.Ticks");
        #endregion Test #0 with DateTime.Now.Ticks

        Stopwatch watch = Stopwatch.StartNew();
        long frequency = Stopwatch.Frequency;
        double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / frequency;

        #region Test #1 with Stopwatch.ElapsedTicks
        startTick = watch.ElapsedTicks;
        Thread.Sleep(SleepTime);
        stopTick = watch.ElapsedTicks;
        double elapsedSw = (stopTick - startTick) * nanosecPerTick;
        Display((int)(elapsedSw / 1000 / 1000), "Stopwatch.ElapsedTicks");
        #endregion Test #1 with Stopwatch.ElapsedTicks

        #region Test #2 with Stopwatch.ElapsedMilliseconds
        startTick = watch.ElapsedMilliseconds;
        Thread.Sleep(SleepTime);
        stopTick = watch.ElapsedMilliseconds;
        Display((int)(stopTick - startTick), "Stopwatch.ElapsedMilliseconds");
        #endregion Test #2 with Stopwatch.ElapsedMilliseconds

        #region Test #3 with Stopwatch.ElapsedTicks after Reset
        watch.Stop();
        watch.Reset();
        watch.Start();
        startTick = watch.ElapsedTicks;
        Thread.Sleep(SleepTime);
        stopTick = watch.ElapsedTicks;
        elapsedSw = (stopTick - startTick) * nanosecPerTick;
        Display((int)(elapsedSw / 1000 / 1000), "Stopwatch.ElapsedTicks after Reset");
        #endregion Test #3 with Stopwatch.ElapsedTicks after Reset

        #region Test #4 with Stopwatch.ElapsedTicks and ThreadAffinity
        Thread.BeginThreadAffinity();
        startTick = watch.ElapsedTicks;
        Thread.Sleep(SleepTime);
        stopTick = watch.ElapsedTicks;
        elapsedSw = (stopTick - startTick) * nanosecPerTick;
        Display((int)(elapsedSw / 1000 / 1000), "Stopwatch.ElapsedTicks setting ThreadAffinity");
        Thread.EndThreadAffinity();
        #endregion Test #4 with Stopwatch.ElapsedTicks and ThreadAffinity

        #region Test #5 with Stopwatch.ElapsedTicks and ProcessorAffinity (and more)
        const int affinity = 0x0001;
        Process proc = Process.GetCurrentProcess();
        proc.ProcessorAffinity = new IntPtr(affinity);
        proc.PriorityClass = ProcessPriorityClass.High;
        ProcessThreadCollection ptc = proc.Threads;
        foreach (ProcessThread pt in ptc)
        {
            pt.IdealProcessor = 0;
            pt.ProcessorAffinity = new IntPtr(affinity);
        }
        Thread.CurrentThread.Priority = ThreadPriority.Highest;

        startTick = watch.ElapsedTicks;
        Thread.Sleep(SleepTime);
        stopTick = watch.ElapsedTicks;
        elapsedSw = (stopTick - startTick) * nanosecPerTick;
        Display((int)(elapsedSw / 1000 / 1000), "Stopwatch.ElapsedTicks setting ProcessorAffinity (and more)");
        #endregion Test #5 with ProcessorAffinity and more

        #region Test #6 with Syncronized object
        elapsedSw = new SyncTimer().Go();
        Display((int)(elapsedSw / 1000 / 1000), "Stopwatch.ElapsedTicks with Syncronized object");
        #endregion Test #6 with Syncronized object
    }

    private static void Display(int milliseconds, string testName)
    {
        Console.WriteLine("{0:0000} ms for {1}", milliseconds, testName);
    }
}

[Synchronization]
internal class SyncTimer : ContextBoundObject
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    public double Go()
    {
        Stopwatch.StartNew();
        long frequency = Stopwatch.Frequency;
        double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / frequency;

        long startTick = Stopwatch.GetTimestamp();
        Thread.Sleep(StopWatchTest.SleepTime);
        long stopTick = Stopwatch.GetTimestamp();
        return (stopTick - startTick) * nanosecPerTick;
    }
}

解决方案

Have a look at the following links:

https://connect.microsoft.com/VisualStudio/feedback/details/94083/stopwatch-returns-negative-elapsed-time

System.Diagnostics.Stopwatch returns negative numbers in Elapsed... properties

It seems there is an issue with Stopwatch accuracy which can lead to it returning negative Elapsed times, and also wildly varying times. If you look at the Connect issue, most of the people there are talking about seeing the issue on a virtual machine, which is where we are seeing the negative Elapsed values issue.

Looking at the QueryPerformanceCounter doc, it seems to imply this issue can happen on multiprocessor systems due to BIOS or hardware abstraction layer bugs, but gives no further information and is not specific about virtualised machines.

As for the solution to this problem... I haven't found one in a lot of googling. You can ignore values less than zero, which is not ideal but workable in some cases. But that doesn't solve your problem - how do you know what values are invalid?

Hope this helps somewhat.

这篇关于.NET System.Diagnostics.Stopwatch问题(返回值过低)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆