C# GetLastInputInfo的整数环绕问题
我想检查应用程序中的用户是否处于非活动状态。我做了一些研究,并选择使用GetLastInputInfo和Environment.TickCount,因为它看起来非常简单。不幸的是,结果有点敏感 GetLastInputInfo返回最后一个“TickCount”值为DWORD的结构(即UInt32)。理论上,我想从Environment.TickCount中减去该值,这就给出了用户处于非活动状态的毫秒数 返回一个Int32。当它们达到最大值时,两者都会环绕,这对于Int32和UInt32是不同的。处理这个问题我有点不舒服,尤其是因为代码基本上无法测试(Environment.TickCount在24.9天后结束,而该特性在24.9天后到期) 以下是我迄今为止所做的工作:C# GetLastInputInfo的整数环绕问题,c#,.net,winapi,int,C#,.net,Winapi,Int,我想检查应用程序中的用户是否处于非活动状态。我做了一些研究,并选择使用GetLastInputInfo和Environment.TickCount,因为它看起来非常简单。不幸的是,结果有点敏感 GetLastInputInfo返回最后一个“TickCount”值为DWORD的结构(即UInt32)。理论上,我想从Environment.TickCount中减去该值,这就给出了用户处于非活动状态的毫秒数 返回一个Int32。当它们达到最大值时,两者都会环绕,这对于Int32和UInt32是不同的。
[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!
}
}
是否有一种足够简单的方法来处理这两个环绕,或者我应该使用另一种方法来检测用户的不活动?另外,对于如何在不使用计算机的情况下进行25天测试的任何建议,我们都表示感谢。由于不活动的时间远小于滴答计数器的容量,所以这根本不是问题 如果其中一个计数器已环绕而另一个计数器未环绕,则减法的结果也将环绕并给出正确的结果。您只需强制转换值,以使数据类型相同:
int idleTime = Environment.TickCount - (int)lastInputInfo.dwTime;
例如,如果Environment.TickCount
已换行为-2147483612,且lastInputInfo.dwTime为2147483624,则-2147483612-2147483624=60
您甚至可以将这两个值向下转换为较小的数据类型,如Int16,只要空闲时间适合该数据类型,减法后仍然可以得到正确的结果。这只是Guffa答案的补充 在依赖整数溢出时,始终使用未选中的
关键字是“最佳实践”。原因有两个:
它让读者知道您有意依赖溢出
虽然未选中是C#中的默认值,但这可以在编译器的命令行上更改
这看起来是正确的,我在F#interactive中做了一些测试来验证:P谢谢!为了确认,假设您使用Win32 GetTickCount()返回uint,结果将是正确的?如果系统正常运行时间达到49.7天,并且最后一次用户交互发生在Environment.TickCount结束之前,只要用户空闲,就没有办法获得空闲时间?请记住,这种方法只能检测到以50天为单位的用户不活动时间。@HristoIliev感谢提醒,但此功能的用例是5分钟-1小时不活动,因此这不是问题。+1是的,这使代码更具信息性,而且更健壮,不依赖于特定的编译器设置。
int idleTime = unchecked(Environment.TickCount - (int)lastInputInfo.dwTime);