我想在我的应用程序中检查用户是否处于不活动状态。我做了一些研究,然后使用GetLastInputInfo和Environment.TickCount,因为它看起来非常简单。不幸的是,事实证明它有点敏感。
GetLastInputInfo返回一个LASTINPUTINFO结构,其最后一个“TickCount”值为DWORD(即UInt32)。从理论上讲,我想从Environment.TickCount中减去该值,这可以让我知道用户已经处于非活动状态的ms。
Environment.TickCount返回一个Int32。两者都会在它们达到最大值时回绕,这对于Int32和UInt32是不同的。我对处理这个问题感到有点不舒服,特别是因为代码基本上无法测试(Environment.TickCount在24.9天后回绕并且该功能在此之前到期)。
这是我到目前为止所做的:
[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天的情况下进行测试的任何建议表示赞赏。
答案 0 :(得分:7)
由于不活动时间比蜱计数器的容量小得多,所以根本不是问题。
如果其中一个计数器已经缠绕而不是另一个,则减法中的结果也会回绕并给出正确的结果。您只需要转换值,使其具有相同的数据类型:
int idleTime = Environment.TickCount - (int)lastInputInfo.dwTime;
如果例如Environment.TickCount
已经回绕到-2147483612并且lastInputInfo.dwTime是2147483624,那么-2147483612 - 2147483624 = 60。
您甚至可以将两个值都转换为较小的数据类型,如Int16,只要空闲时间适合数据类型,您仍然可以在减法后获得正确的结果。
答案 1 :(得分:3)
这只是对Guffa答案的补充。
依靠整数溢出来始终使用unchecked
关键字是“最佳做法”。这有两个原因:
Checked and Unchecked (C# Reference)
int idleTime = unchecked(Environment.TickCount - (int)lastInputInfo.dwTime);