4

アプリケーションでユーザーの非アクティブを確認したいと考えています。少し調べてみたところ、GetLastInputInfo と Environment.TickCount を使用することにしました。非常に単純に思えたからです。残念ながら、少し扱いに​​くいことがわかりました。

GetLastInputInfo は、最後の "TickCount" 値を DWORD (つまり UInt32) として持つLASTINPUTINFO構造体を返します。理論的には、Environment.TickCount からその値を差し引くと、ユーザーが非アクティブであったミリ秒数がわかります。

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 日間専用のコンピューターを使用せずにこれをテストする方法についてのアドバイスもいただければ幸いです。

4

2 に答える 2

7

非アクティブの期間はティックカウンターの容量よりもかなり短いため、まったく問題ありません。

カウンターの1つがラップアラウンドし、他のカウンターがラップアラウンドしていない場合、減算の結果もラップアラウンドし、正しい結果が得られます。同じデータ型になるように値をキャストする必要があります。

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

たとえばEnvironment.TickCount、-2147483612にラップアラウンドし、lastInputInfo.dwTimeが2147483624の場合、-2147483612 --2147483624=60になります。

両方の値をInt16などのより小さなデータ型にキャストすることもできます。アイドル時間がデータ型に収まる限り、減算後も正しい結果が得られます。

于 2012-06-27T17:09:12.707 に答える
4

これは、Guffa の回答に対する単なる補足です。

整数オーバーフローに依存する場合は、常にuncheckedキーワードを使用するのが「ベスト プラクティス」です。これには 2 つの理由があります。

  1. 意図的にオーバーフローに依存していることを読者に知らせます
  2. C# ではチェックなしがデフォルトですが、これはコンパイラのコマンドラインで変更できます。

チェックありとチェックなし (C# リファレンス)

int idleTime = unchecked(Environment.TickCount - (int)lastInputInfo.dwTime);
于 2012-06-27T18:44:15.330 に答える