Я решил проблему, используя несколько различных техник, чтобы дать мне довольно хорошее решение.Я использую GetLastInput, чтобы работать, когда система в последний раз была затронута. Это хорошо документировано в другом месте, но вот мой метод:
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;
}
}
Это говорит только о том, что система бездействует, а не приложение.Если пользователь нажимает на Word и работает там в течение часа, я все еще хочу тайм-аут.Чтобы справиться с этим случаем, я просто помню, как мое приложение теряет фокус, переопределяя методы OnDeactivation и OnActivation для объекта приложения:
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);
}
Моя подпрограмма IsIdle была добавлена в объект приложения.Он обрабатывает глобальный случай, когда приложение имеет фокус, но ничего не произошло (IsMachineIdle) и конкретный случай, когда приложение теряет фокус, пока пользователь выполняет другие действия (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;
}
}
Последнее, что я сделалбыло создать цикл таймера, который опрашивал это событие флага несколько секунд.
Кажется, это работает нормально.