Environment.Tickcount VS Datetime.Now

Environment.TickCount vs DateTime.Now

Use Stopwatch class. There is a decent example on msdn: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

    Stopwatch stopWatch = Stopwatch.StartNew();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;

How Environment.TickCount overflows after 25 days (or 48-49 days)

For starters, TickCount returns milliseconds, not ticks in the sense of DateTime.Ticks. It does so with a precision the same as the system timer, which is about 10-16 milliseconds.

The documentation explains how the value cycles:

Because the value of the TickCount property value is a 32-bit signed integer, if the system runs continuously, TickCount will increment from zero to Int32.MaxValue for approximately 24.9 days, then jump to Int32.MinValue, which is a negative number, then increment back to zero during the next 24.9 days. You can work around this issue by calling the Windows GetTickCount function, which resets to zero after approximately 49.7 days, or by calling the GetTickCount64 function.

Doing the maths, we find out that 24.9 days is 2,151,360,000 (compared to Int.MaxValue of 2,147,483,647). MaxValue + |MinValue| yields 4294967295, which if divided by 86400000 milliseconds (1 day) yields about 49.7 days, as the documentation suggests.

Source

DateTime from TickCount?

You can't, without more information (and even then it can be ambiguous). Environment.TickCount returns:

A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.

... so unless you can find out the time the computer was started from somewhere, you're out of luck. There may well be registry entries or system calls you can make to find out the last boot time, but I don't know them off the top of my head. Of course, you can get an approximate value by taking Environment.TickCount yourself and DateTime.UtcNow as soon after (or before) that as possible, and finding the difference between the two:

public static DateTime UnreliableDateTimeFromTickCount(int tickCount)
{
DateTime now = DateTime.UtcNow;
DateTime boot = now - TimeSpan.FromMilliseconds(Environment.TickCount);
return boot + TimeSpan.FromMilliseconds(tickCount);
}

However, even with that, the value will cycle round every 24.9 days, so if the computer has been on for longer than that, the count is ambiguous.

I'd suggest avoiding using Environment.TickCount if possible, basically - is this under your control at all?

Environment.TickCount is not enough

public void BootTime(){    
SelectQuery query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary='true'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

foreach (ManagementObject mo in searcher.Get())
{
DateTime dtBootTime = ManagementDateTimeConverter.ToDateTime(mo.Properties["LastBootUpTime"].Value.ToString());
Console.WriteLine(dtBootTime.ToString());
}
}

Is Environment.TickCount affected by system time adjustments?

No, Environment.TickCount is not affected by adjustments of the system time. That was my interpretation of the documentation, but my curiosity demanded harder proof, so I had the following code run while adjusting the system back and forth one hour:

while (true)
{
Console.WriteLine(Environment.TickCount);
Thread.Sleep(1000);
}

...and the output showed a perfect sequence that was not affected by the time adjustments.

Update
So I did some more homework, triggered by Marcus' question in the comments below. I am quite sure (could not confirm though) that Environment.TickCount makes a call to GetTickCount that has the following mentioned in the docs:

The resolution of the GetTickCount
function is limited to the resolution
of the system timer, which is
typically in the range of 10
milliseconds to 16 milliseconds. The
resolution of the GetTickCount
function is also affected by
adjustments made by the
GetSystemTimeAdjustment function.

So, while it is not affected by altering the system time, it seems that will be affected by adjustments that are caused by a call to SetSystemTimeAdjustment.

Should I make a wrapper class for Environment.TickCount?

While I think it is duplicate of discussion on TickCount vs. Now...

Is TickCount the best tool you need to decide yourself. If 100ms matters for 1 million of operations you plan to measure - probably, but I strongly doubt as precision of TickCount is 10ms your average error for that many measurements would be about 5ms*10^6.

I think you should create wrapper class for your time measurement, but mainly not to protect from wraparound, but to allow unit testing of your code. It is not easy to mock system-wide time functions, but custom class can be setup for ease of use and testing.

How many ways are there to measure time?

What's up with that?

The first sentence of each of the documentation pages you link to give a pretty clear description of their purpose (emphasis added):

  • DateTime.Now

the current date and time on this computer, expressed as the local time.

  • Environment.TickCount

Gets the number of milliseconds elapsed since the system started.

  • StopWatch

Provides a set of methods and properties that you can use to accurately measure elapsed time.

  • DateTime

Represents an instant in time, typically expressed as a date and time of day.

  • TimeSpan

Represents a time interval.

(a difference between two points in time)

So DateTime and TimeSpan are not interchangeable, and more than Location and Distance are. They are related but represent different things.

If any of those are not clear, or you need further clarification, please say specifically what you're confused about.


Also, the definition of "Tick" seems to be inconsistent.

Because they're define _within the context of where they're defined. There's not an "industry-standard" definition for "ticks" that I'm aware of. Some types (like Stopwatch) sacrifice range for greater precision, while others (like DateTime) allow for much larger ranges but cannot be millisecond-precise.


Are there any others?

One that you haven't mentioned is:

  • Timer

Generates an event after a set interval, with an option to generate recurring events.

Again, it serves a different purpose. It's designed to do something at regular intervals.

I'm not sure how broad your scope is to know if there are "any others". If you have a specific need that isn't met by one of these classes then add that to your question.



Related Topics



Leave a reply



Submit