Integer problem with GetLastInputInfo

I want to check user inactivity in my application. I did a bit of work and went to use GetLastInputInfo and Environment.TickCount, because it seemed very simple. Unfortunately, this turns out to be a little touching.

GetLastInputInfo returns a LASTINPUTINFO structure that has the last TickCount value as DWORD (i.e., UInt32). Theoretically, I want to subtract this value from Environment.TickCount, and this gives me how many ms the user was inactive.

Environment.TickCount returns Int32. Both will turn around when they reach their maximum value, which is different for Int32 and UInt32. I'm a little uncomfortable with this, especially because the code essentially cannot be tested (Environment.TickCount wraps up after 24.9 days, and the function is before it).

Here is what I have done so far:

[DllImport("user32.dll")] static extern bool GetLastInputInfo(out LastInputInfo plii); struct LastInputInfo { public uint cbSize; public uint dwTime; } //(...) var lastInputInfo = new LastInputInfo(); lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo); if (GetLastInputInfo(out lastInputInfo)) { // The next line obviously will not work when either of the terms has wrapped around var idleTime = Environment.TickCount - lastInputInfo.dwTime; if (idleTime > mTimeOut) { // user is inactive! } } 

Is there a simple enough way to handle wrappers or use a different approach to completely detect user inaction? Any advice on how to test this without a computer dedication for 25 days is also welcome.

+4
source share
2 answers

Since the period of inactivity is much less than the capacity of tick counters, this is not a problem at all.

If one of the counters is wrapped around and not the other, the result in the subtraction will also turn around and give the correct result. You just need to specify the values ​​so that they are the same:

 int idleTime = Environment.TickCount - (int)lastInputInfo.dwTime; 

If, for example, Environment.TickCount wrapped to -2147483612, and lastInputInfo.dwTime is 2147483624, then -2147483612 - 2147483624 = 60.

You can even reset both values ​​to a smaller data type, such as Int16, and you will still get the correct result after subtraction if the downtime matches the data type.

+7
source

This is just a complement to Guff's answer.

This is "best practice" when you rely on integer overflows to always use the unchecked keyword. There are two reasons for this:

  • This allows the reader to know that you intentionally rely on overflow.
  • If C # does not specify a default value, this can be changed at the compiler command line.

Checked and removed (link to C #)

 int idleTime = unchecked(Environment.TickCount - (int)lastInputInfo.dwTime); 
+3
source

All Articles