me resolvió el problema utilizando algunas técnicas diferentes enrolladas que me diera una solución bastante buena. Yo uso GetLastInput a trabajar a cabo cuando el sistema fue tocado por último Esto está bien documentado en otros lugares, pero aquí está mi método:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
}
Esto sólo me dice que cuando el sistema ha estado inactivo, no de la aplicación. Si el usuario hace clic en Word y trabaja allí durante una hora, todavía quiero un tiempo de espera. Para manejar este caso, simplemente me acuerdo cuando mi aplicación pierde el foco reemplazando el OnDeactivated y OnActivated métodos en el objeto de aplicación: se añadió
override protected void OnDeactivated(EventArgs e)
{
this._lostFocusTime = DateTime.Now;
base.OnDeactivated(e);
}
protected override void OnActivated(EventArgs e)
{
this._lostFocusTime = null;
base.OnActivated(e);
}
Mi rutina IsIdle al objeto de aplicación. Maneja el caso global, donde la aplicación tiene el foco, pero no pasó nada (IsMachineIdle) y el caso específico en el que la aplicación pierde foco mientras que el usuario está haciendo otras cosas (isAppIdle):
public bool IsIdle
{
get
{
TimeSpan activityThreshold = TimeSpan.FromMinutes(1);
TimeSpan machineIdle = Support.User32Interop.GetLastInput();
TimeSpan? appIdle = this._lostFocusTime == null ? null : (TimeSpan?)DateTime.Now.Subtract(_lostFocusTime.Value);
bool isMachineIdle = machineIdle > activityThreshold ;
bool isAppIdle = appIdle != null && appIdle > activityThreshold ;
return isMachineIdle || isAppIdle;
}
}
Lo último que hice fue crear un bucle de temporizador que sondeó este evento de bandera unos segundos.
Esto parece funcionar bien.
Tenga en cuenta que _lostFocusTime debe declararse como DateTime? variable. Si intenta declarar como DateTime, no puede NULL el valor. – Saren
Environment.TickCount tiene tipo int, y se ve obligado a ajustar cada 24,9 días. LASTINPUTINFO.dwTime tiene type uint, por lo que no se ajusta hasta 49.7 días. Si la máquina ha estado encendida durante más de 24.9 días, entonces las matemáticas en el ejemplo están arruinadas. Alivié el problema reemplazando Environment.TickCount con una llamada a la función WINAPI GetTickCount, que también devuelve un valor de uint.No estoy seguro de lo que sucede si la última entrada fue a 49.5 días y el conteo de ticks actual es de 50.0 días. [Según esta respuesta a otra pregunta] (http://stackoverflow.com/a/1078089/2998072) debería estar bien. –