rubenvb February 2016

How to improve CPU usage when automatically "locking" a (WPF) application using Window.PreviewMouseMoveEvent?

Currently I'm using

 EventManager.RegisterClassHandler(typeof(Window),
                                   Window.PreviewMouseMoveEvent,
                                   new MouseEventHandler(OnPreviewMouseMove));

where OnPreviewMouseMove just calls Stop() and Start() on the timer used to handle automatic timeout of my application (users should re-enter credentials after a period of inactivity).

I've noticed that this solution uses quite a bit of CPU power (as in, 3-12% on a Core i7 when I'm jittering the mouse over the window), so I wonder if there might be a better way to handle this. I understand that the jittery mouse movement and relatively low CPU usage won't be a real problem, but I am open to better ways to handle this.

I'm also unsure whether this can be made to work for non-WPF applications (my guess is I'll need different events in this case), but that might be matter for another question.

Answers


Scott Chamberlain February 2016

Use the Windows API call GetLastInputInfo to figure out when the last keyboard press or mouse movement happened. This is the same timer that the screensaver uses to figure out when to turn on.

Here is a wrapper class I have used in other projects. The Idle event runs on the current SynchronizationContext or a threadpool thread if there is not one set.

/// <summary>
/// A timer that raises the <see cref="Idle"/> event when it detects the session 
/// </summary>
public sealed class SystemIdleTimer : IDisposable
{
    private readonly System.Threading.Timer _timer;
    private readonly SynchronizationContext _synchronizationContext;

    /// <summary>
    /// This event is rasied when the sysstem's idle time is greater than <see cref="MaxIdleTime"/>.
    /// This event is posted to the SynchronizationContext that the constructor was run under.
    /// </summary>
    public event EventHandler Idle;

    /// <summary>
    /// The amount of idle time that must pass before the <see cref="Idle"/> event is raised.
    /// </summary>
    public TimeSpan MaxIdleTime { get; set; }

    /// <summary>
    /// Is the user currently detected as idle;
    /// </summary>
    public bool IsDetectedIdle { get; private set; }

    /// <summary>
    /// Creates a new timer with a specified trigger level and a check frequency of once a minute.
    /// </summary>
    /// <param name="maxIdleTime">The amount of idle time that must pass before the <see cref="Idle"/> event is raised.</param>
    public SystemIdleTimer(TimeSpan maxIdleTime)
        : this(maxIdleTime, TimeSpan.FromMinutes(1))
    {
    }

    /// <summary>
    /// Creates a new timer with a specified trigger level and a check frequency.
    /// </summa 

Post Status

Asked in February 2016
Viewed 3,457 times
Voted 5
Answered 1 times

Search




Leave an answer