1
1
using 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 ;
4
4
5
- namespace ComputerLock . Platforms ;
6
-
7
- public class UserActivityMonitor
5
+ namespace ComputerLock . Platforms
8
6
{
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
15
8
{
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 ( )
17
18
{
18
- _autoLockMillisecond = autoLockSecond * 1000 ;
19
+ _dispatcher = Dispatcher . CurrentDispatcher ;
20
+
21
+ _timer = new DispatcherTimer ( TimeSpan . FromSeconds ( 1 ) , DispatcherPriority . Normal , Timer_Tick , _dispatcher ) ;
22
+ _timer . Start ( ) ;
19
23
}
20
- }
21
24
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 )
25
50
{
26
- if ( _timer == null )
51
+ if ( ! _isMonitoring || _disposed )
27
52
{
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
+ }
31
68
}
32
- _timer . Start ( ) ;
33
69
}
34
- }
35
70
36
- public void StopMonitoring ( )
37
- {
38
- lock ( _lock )
71
+ private void RunOnUIThread ( Action action )
39
72
{
40
- if ( _timer != null )
73
+ if ( _disposed )
74
+ {
75
+ return ;
76
+ }
77
+
78
+ if ( _dispatcher . CheckAccess ( ) )
41
79
{
42
- _timer . Elapsed -= Timer_Elapsed ;
43
- _timer . Stop ( ) ;
44
- _timer . Dispose ( ) ;
45
- _timer = null ;
80
+ action ( ) ;
81
+ }
82
+ else
83
+ {
84
+ _dispatcher . Invoke ( action ) ;
46
85
}
47
86
}
48
- }
49
87
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
+ }
54
93
55
- if ( WinApi . GetLastInputInfo ( ref lastInputInfo ) )
94
+ protected virtual void Dispose ( bool disposing )
56
95
{
57
- long elapsedMillisecond = Environment . TickCount64 - lastInputInfo . dwTime ;
58
- if ( elapsedMillisecond > _autoLockMillisecond )
96
+ if ( _disposed )
97
+ {
98
+ return ;
99
+ }
100
+
101
+ if ( disposing )
59
102
{
60
- OnIdle ? . Invoke ( this , EventArgs . Empty ) ;
103
+ RunOnUIThread ( ( ) =>
104
+ {
105
+ _timer . Stop ( ) ;
106
+ _timer . Tick -= Timer_Tick ;
107
+ } ) ;
61
108
62
- // 避免死锁,异步停止监控
63
- Task . Run ( StopMonitoring ) ;
109
+ OnIdle = null ;
64
110
}
111
+ _disposed = true ;
65
112
}
66
113
}
67
- }
114
+ }
0 commit comments