.NET 组件,简化系统空闲时间跟踪






4.70/5 (15投票s)
一个 .NET 组件,简化系统空闲时间跟踪。
引言
通常,需要跟踪系统的空闲时间,并在系统空闲一段时间后执行代码。 尽管 .NET 框架没有为此提供内置功能,但使用 P/Invoke 实现起来非常容易。 无论如何,我想开发一个组件,您可以将其放在窗体上并设置参数,它将完成其余操作。 所以,这就是它。
获取系统空闲时间
首先,稍微解释一下如何跟踪系统的空闲时间。 由于 .NET 框架没有为此提供内置功能,因此我们必须使用 Win32 API。 我们可以使用 GetLastInputInfo
函数来实现此目的。 GetLastInputInfo
函数位于 User32.dll 中。
<DllImport("User32.dll")> _
Private Shared Function GetLastInputInfo(ByRef lii As LASTINPUTINFO) As Boolean
End Function
由于 GetLastInputInfo
需要一个 LASTINPUTINFO
结构体,因此也必须定义它。
Public Structure LASTINPUTINFO
Public cbSize As UInteger
Public dwTime As UInteger
End Structure
并且,将返回总空闲时间的函数是
Public Shared Function GetIdle() As UInteger
Dim lii As New LASTINPUTINFO()
lii.cbSize = Convert.ToUInt32((Marshal.SizeOf(lii)))
GetLastInputInfo(lii)
Return Convert.ToUInt32(Environment.TickCount) - lii.dwTime
End Function
这是查找总空闲时间所需的所有代码。 所有与 Win32 API 相关的代码都位于 Win32Wrapper
类中。 这是完整的 Win32Wrapper
类。
Public Class Win32Wrapper
Public Structure LASTINPUTINFO
Public cbSize As UInteger
Public dwTime As UInteger
End Structure
<DllImport("User32.dll")> _
Private Shared Function GetLastInputInfo(ByRef lii As LASTINPUTINFO) As Boolean
End Function
Public Shared Function GetIdle() As UInteger
Dim lii As New LASTINPUTINFO()
lii.cbSize = Convert.ToUInt32((Marshal.SizeOf(lii)))
GetLastInputInfo(lii)
Return Convert.ToUInt32(Environment.TickCount) - lii.dwTime
End Function
End Class
SystemIdleTimer 组件
我的主要目标是创建一个易于使用的组件。 结果是 SystemIdleTimer
组件只有几个属性。 该组件具有一个 MaxIdleTime
属性,用于定义最大空闲时间(以秒为单位)。
例如,要将 MaxIdleTime
设置为 2 秒,可以使用以下代码
SystemIdleTimer1.MaxIdleTime = 2
该组件公开以下事件
OnEnterIdleState
- 当系统空闲时间达到MaxIdleTime
属性中定义的时间量时,将触发此事件。OnExitIdleState
- 当系统退出空闲状态时,将触发此事件。
SystemIdleTimer
的 Start
方法用于开始跟踪空闲时间。 还有一个 Stop
方法可用。
这是 SystemIdleTimer
类代码
Public Class SystemIdleTimer _
Inherits Component
Private Const INTERNAL_TIMER_INTERVAL As Double = 550
<Description("Event that if fired when idle state is entered.")> _
Public Event OnEnterIdleState(ByVal sender As Object, ByVal e As IdleEventArgs)
<Description("Event that is fired when leaving idle state.")> _
Public Event OnExitIdleState(ByVal sender As Object, ByVal e As IdleEventArgs)
Private ticker As Timers.Timer
Private m_MaxIdleTime As Integer
Private m_LockObject As Object
Private m_IsIdle As Boolean = False
<Description("Maximum idle time in seconds.")> _
Public Property MaxIdleTime() As UInteger
Get
Return m_MaxIdleTime
End Get
Set(ByVal value As UInteger)
If value = 0 Then
Throw New ArgumentException("MaxIdleTime must be larger then 0.")
Else
m_MaxIdleTime = value
End If
End Set
End Property
Public Sub New()
m_LockObject = New Object()
ticker = New Timers.Timer(INTERNAL_TIMER_INTERVAL)
AddHandler ticker.Elapsed, AddressOf InternalTickerElapsed
End Sub
Public Sub Start()
ticker.Start()
End Sub
Public Sub [Stop]()
ticker.Stop()
SyncLock m_LockObject
m_IsIdle = False
End SyncLock
End Sub
Public ReadOnly Property IsRunning() As Boolean
Get
Return ticker.Enabled
End Get
End Property
Private Sub InternalTickerElapsed(ByVal sender As Object, _
ByVal e As Timers.ElapsedEventArgs)
Dim idleTime As UInteger = Win32Wrapper.GetIdle()
If idleTime > (MaxIdleTime * 1000) Then
If m_IsIdle = False Then
SyncLock m_LockObject
m_IsIdle = True
End SyncLock
Dim args As New IdleEventArgs(e.SignalTime)
RaiseEvent OnEnterIdleState(Me, args)
End If
Else
If m_IsIdle Then
SyncLock m_LockObject
m_IsIdle = False
End SyncLock
Dim args As New IdleEventArgs(e.SignalTime)
RaiseEvent OnExitIdleState(Me, args)
End If
End If
End Sub
End Class
还需要 IdleEventArgs
类才能触发 OnEnterIdleState
和 OnExitIdleState
事件。
Public Class IdleEventArgs_
Inherits EventArgs
Private m_EventTime As DateTime
Public ReadOnly Property EventTime() As DateTime
Get
Return m_EventTime
End Get
End Property
Public Sub New(ByVal timeOfEvent As DateTime)
m_EventTime = timeOfEvent
End Sub
End Class
使用 SystemIdleTimer 组件
您所要做的就是将 SystemIdleTimer
组件放在您的窗体上,然后定义 SystemIdleTimer
组件的 MaxIdleTime
属性。
然后,定义需要在 OnEnterIdleState
和 OnExitIdleState
事件上执行的代码。
并且在您的代码中的某个位置,使用其 Start
方法启动 SystemIdleTimer
组件。 例如
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
SystemIdleTimer1.Start()
End Sub
就这样了。 希望这篇文章对您有所帮助。