Eine weitere Möglichkeit ist die Verwendung der Windows-API-Methode GetLastInputInfo .
Einige Hohlräume
- Ich nehme an, Windows, weil es WPF ist
- Prüfen Sie, ob Ihr Kiosk GetLastInputInfo unterstützt
- Ich weiß nichts über MVVM. Diese Methode verwendet eine Technik, die UI agnostic ist, so würde ich denken, es würde für Sie arbeiten.
Die Verwendung ist einfach. Rufen Sie UserIdleMonitor.RegisterForNotification auf. Sie geben eine Benachrichtigungsmethode und eine Zeitspanne an. Wenn eine Benutzeraktivität auftritt und dann für den angegebenen Zeitraum aufhört, wird die Benachrichtigungsmethode aufgerufen. Sie müssen sich erneut registrieren, um eine weitere Benachrichtigung zu erhalten, und können die Registrierung jederzeit aufheben. Wenn 49,7 Tage lang (plus die idlePeriod) keine Aktivität stattfindet, wird die Benachrichtigungsmethode aufgerufen.
public static class UserIdleMonitor
{
static UserIdleMonitor()
{
registrations = new List<Registration>();
timer = new DispatcherTimer(TimeSpan.FromSeconds(1.0), DispatcherPriority.Normal, TimerCallback, Dispatcher.CurrentDispatcher);
}
public static TimeSpan IdleCheckInterval
{
get { return timer.Interval; }
set
{
if (Dispatcher.CurrentDispatcher != timer.Dispatcher)
throw new InvalidOperationException("UserIdleMonitor can only be used from one thread.");
timer.Interval = value;
}
}
public sealed class Registration
{
public Action NotifyMethod { get; private set; }
public TimeSpan IdlePeriod { get; private set; }
internal uint RegisteredTime { get; private set; }
internal Registration(Action notifyMethod, TimeSpan idlePeriod)
{
NotifyMethod = notifyMethod;
IdlePeriod = idlePeriod;
RegisteredTime = (uint)Environment.TickCount;
}
}
public static Registration RegisterForNotification(Action notifyMethod, TimeSpan idlePeriod)
{
if (notifyMethod == null)
throw new ArgumentNullException("notifyMethod");
if (Dispatcher.CurrentDispatcher != timer.Dispatcher)
throw new InvalidOperationException("UserIdleMonitor can only be used from one thread.");
Registration registration = new Registration(notifyMethod, idlePeriod);
registrations.Add(registration);
if (registrations.Count == 1)
timer.Start();
return registration;
}
public static void Unregister(Registration registration)
{
if (registration == null)
throw new ArgumentNullException("registration");
if (Dispatcher.CurrentDispatcher != timer.Dispatcher)
throw new InvalidOperationException("UserIdleMonitor can only be used from one thread.");
int index = registrations.IndexOf(registration);
if (index >= 0)
{
registrations.RemoveAt(index);
if (registrations.Count == 0)
timer.Stop();
}
}
private static void TimerCallback(object sender, EventArgs e)
{
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = Marshal.SizeOf(typeof(LASTINPUTINFO));
if (GetLastInputInfo(out lii))
{
TimeSpan idleFor = TimeSpan.FromMilliseconds((long)unchecked((uint)Environment.TickCount - lii.dwTime));
//Trace.WriteLine(String.Format("Idle for {0}", idleFor));
for (int n = 0; n < registrations.Count; )
{
Registration registration = registrations[n];
TimeSpan registeredFor = TimeSpan.FromMilliseconds((long)unchecked((uint)Environment.TickCount - registration.RegisteredTime));
if (registeredFor >= idleFor && idleFor >= registration.IdlePeriod)
{
registrations.RemoveAt(n);
registration.NotifyMethod();
}
else n++;
}
if (registrations.Count == 0)
timer.Stop();
}
}
private static List<Registration> registrations;
private static DispatcherTimer timer;
private struct LASTINPUTINFO
{
public int cbSize;
public uint dwTime;
}
[DllImport("User32.dll")]
private extern static bool GetLastInputInfo(out LASTINPUTINFO plii);
}
Aktualisiert
Es wurde ein Problem behoben, bei dem es zu einem Deadlock kommen konnte, wenn man versuchte, sich über die Benachrichtigungsmethode neu zu registrieren.
Vorzeichenlose Mathematik korrigiert und ungeprüft hinzugefügt.
Leichte Optimierung im Timer-Handler, um Benachrichtigungen nur bei Bedarf zuzuweisen.
Die Debugging-Ausgabe wurde auskommentiert.
Geändert, um DispatchTimer zu verwenden.
Die Möglichkeit zur Aufhebung der Registrierung wurde hinzugefügt.
Thread-Prüfungen in öffentlichen Methoden hinzugefügt, da diese nicht mehr thread-sicher sind.