.NET System.Diagnostics.Stopwatch issue (returns values too low)

前端 未结 7 1100
眼角桃花
眼角桃花 2021-02-13 23:14

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 a

相关标签:
7条回答
  • 2021-02-13 23:50

    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.

    0 讨论(0)
  • 2021-02-13 23:53

    I know this an old question, but I thought I'd provide my 2 cents after struggling with the same problem:

    I started looking at the Frequency as suggested by @AllonGuralnek and it did provide the accurate time in seconds, but it dropped the remaining milliseconds which I also wanted to capture.

    Anyway, after a lot of back and forth and not getting anywhere with this, I noticed that the sw.Elapsed had a Ticks property and this one provided me with the accurate number of ticks and once converted back it provided me with an accurate time.

    Code wise, this is what I ended up with:

    Stopwatch sw = new Stopwatch();
    sw.Start();
    
    ... DO WORK
    
    sw.Stop();
    
    long elapsedTicks = sw.Elapsed.Ticks;
    Debug.WriteLine(TimeSpan.FromTicks(elapsedTicks).ToString());
    

    When running a test, calling:

    • sw.Elapsed.ToString() : "00:00:11.6013029"

    • sw.ElapsedTicks : Returns "40692243" and converts to "00:00:04.0692243" when calling TimeSpan.FromTicks(sw.ElapsedTicks).ToString() which is inaccurate.

    • sw.Elapsed.Ticks : Returns "116013029" and converts to "00:00:11.6013029" when calling TimeSpan.FromTicks(sw.Elapsed.Ticks).ToString() which accurate.

    While I may be missing something, I feel it doesn't make sense that sw.ElaspedTicks returns a different value than sw.Elapsed.Ticks, so if someone wants to shed some light on this, please do, but from my point of view, I see it as a bug and if not, at least it feels very inconsistent!.

    NOTE: Calling sw.ElapsedTicks / Stopwatch.Frequency returns 11 (i.e. seconds) but as I said, it drops the milliseconds which is no use to me.

    0 讨论(0)
  • 2021-02-14 00:02

    I believe you'll find the answer here: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/eec73d6e-f597-4342-be48-5d2ce30202f0/

    but for more detail and explanation see also: http://msdn.microsoft.com/en-us/magazine/cc163996.aspx http://stackoverflow.com/questions/394020/stopwatch-accuracy http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

    0 讨论(0)
  • 2021-02-14 00:06

    Seems like you're using Tick count in some cases. Remember that by default on modern Windows for example, the OS will save CPU. This means that the tick count and the time elapsed are not in linear proportion.

    I suggest you try using the Stopwatch.ElapsedMilliseconds in the most basic form:

    var sw = new Stopwatch();
    sw.Start();
    Thread.Sleep(1000);
    var elpased = sw.Elapsed;
    
    0 讨论(0)
  • 2021-02-14 00:09

    I got this:

    1000 ms for DateTime.Now.Ticks
    0999 ms for Stopwatch.ElapsedTicks
    1000 ms for Stopwatch.ElapsedMilliseconds
    0999 ms for Stopwatch.ElapsedTicks after Reset
    0999 ms for Stopwatch.ElapsedTicks setting ThreadAffinity
    0999 ms for Stopwatch.ElapsedTicks setting ProcessorAffinity (and more)
    

    (Couldn't run the last test)

    On a quad-core i7 machine with .NET4 in Linqpad.

    I only ever tend to use Stopwatch.ElapsedMilliseconds but I've never seen anything odd about it. It does sound like there's something broken about your machine or virtualization platform.

    0 讨论(0)
  • 2021-02-14 00:14

    If the Stopwatch doesn't work, you can use the QueryPerformanceCounter on Windows.

    See this little class on http://www.windojitsu.com/code/hirestimer.cs.html

    0 讨论(0)
提交回复
热议问题