11using System . Runtime . InteropServices ;
2- using System . Timers ;
3- using Timer = System . Timers . Timer ;
2+ using System . Windows . Threading ;
3+ using Dispatcher = System . Windows . Threading . Dispatcher ;
44
5- namespace ComputerLock . Platforms ;
6-
7- public class UserActivityMonitor
5+ namespace ComputerLock . Platforms
86{
9- private Timer ? _timer ;
10- public EventHandler ? OnIdle ;
11- private int _autoLockMillisecond ;
12- private readonly object _lock = new ( ) ;
13-
14- public void SetAutoLockSecond ( int autoLockSecond )
7+ public class UserActivityMonitor : IDisposable
158 {
16- lock ( _lock )
9+ private readonly DispatcherTimer _timer ;
10+ private int _autoLockMillisecond ;
11+ private bool _isMonitoring ;
12+ private readonly Dispatcher _dispatcher ;
13+ private bool _disposed ;
14+
15+ public event EventHandler ? OnIdle ;
16+
17+ public UserActivityMonitor ( )
1718 {
18- _autoLockMillisecond = autoLockSecond * 1000 ;
19+ _dispatcher = Dispatcher . CurrentDispatcher ;
20+
21+ _timer = new DispatcherTimer ( TimeSpan . FromSeconds ( 1 ) , DispatcherPriority . Normal , Timer_Tick , _dispatcher ) ;
22+ _timer . Start ( ) ;
1923 }
20- }
2124
22- public void StartMonitoring ( )
23- {
24- lock ( _lock )
25+ public void SetAutoLockSecond ( int autoLockSecond )
26+ {
27+ RunOnUIThread ( ( ) =>
28+ {
29+ _autoLockMillisecond = autoLockSecond * 1000 ;
30+ } ) ;
31+ }
32+
33+ public void StartMonitoring ( )
34+ {
35+ RunOnUIThread ( ( ) =>
36+ {
37+ _isMonitoring = true ;
38+ } ) ;
39+ }
40+
41+ public void StopMonitoring ( )
42+ {
43+ RunOnUIThread ( ( ) =>
44+ {
45+ _isMonitoring = false ;
46+ } ) ;
47+ }
48+
49+ private void Timer_Tick ( object ? sender , EventArgs e )
2550 {
26- if ( _timer == null )
51+ if ( ! _isMonitoring || _disposed )
2752 {
28- _timer = new Timer ( ) ;
29- _timer . Interval = 1000 ;
30- _timer . Elapsed += Timer_Elapsed ;
53+ return ;
54+ }
55+
56+ var lastInputInfo = new WinApi . LastInputInfo ( ) ;
57+ lastInputInfo . cbSize = ( uint ) Marshal . SizeOf ( lastInputInfo ) ;
58+
59+ if ( WinApi . GetLastInputInfo ( ref lastInputInfo ) )
60+ {
61+ long elapsedMillisecond = Environment . TickCount64 - lastInputInfo . dwTime ;
62+ if ( elapsedMillisecond > _autoLockMillisecond )
63+ {
64+ OnIdle ? . Invoke ( this , EventArgs . Empty ) ;
65+ // 触发一次后停止监控
66+ StopMonitoring ( ) ;
67+ }
3168 }
32- _timer . Start ( ) ;
3369 }
34- }
3570
36- public void StopMonitoring ( )
37- {
38- lock ( _lock )
71+ private void RunOnUIThread ( Action action )
3972 {
40- if ( _timer != null )
73+ if ( _disposed )
74+ {
75+ return ;
76+ }
77+
78+ if ( _dispatcher . CheckAccess ( ) )
4179 {
42- _timer . Elapsed -= Timer_Elapsed ;
43- _timer . Stop ( ) ;
44- _timer . Dispose ( ) ;
45- _timer = null ;
80+ action ( ) ;
81+ }
82+ else
83+ {
84+ _dispatcher . Invoke ( action ) ;
4685 }
4786 }
48- }
4987
50- private void Timer_Elapsed ( object ? sender , ElapsedEventArgs e )
51- {
52- var lastInputInfo = new WinApi . LastInputInfo ( ) ;
53- lastInputInfo . cbSize = ( uint ) Marshal . SizeOf ( lastInputInfo ) ;
88+ public void Dispose ( )
89+ {
90+ Dispose ( true ) ;
91+ GC . SuppressFinalize ( this ) ;
92+ }
5493
55- if ( WinApi . GetLastInputInfo ( ref lastInputInfo ) )
94+ protected virtual void Dispose ( bool disposing )
5695 {
57- long elapsedMillisecond = Environment . TickCount64 - lastInputInfo . dwTime ;
58- if ( elapsedMillisecond > _autoLockMillisecond )
96+ if ( _disposed )
97+ {
98+ return ;
99+ }
100+
101+ if ( disposing )
59102 {
60- OnIdle ? . Invoke ( this , EventArgs . Empty ) ;
103+ RunOnUIThread ( ( ) =>
104+ {
105+ _timer . Stop ( ) ;
106+ _timer . Tick -= Timer_Tick ;
107+ } ) ;
61108
62- // 避免死锁,异步停止监控
63- Task . Run ( StopMonitoring ) ;
109+ OnIdle = null ;
64110 }
111+ _disposed = true ;
65112 }
66113 }
67- }
114+ }
0 commit comments