65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (15投票s)

2008年7月13日

CPOL

2分钟阅读

viewsIcon

52548

downloadIcon

2724

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

SystemIdleTimer Demo Application

引言

通常,需要跟踪系统的空闲时间,并在系统空闲一段时间后执行代码。 尽管 .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 - 当系统退出空闲状态时,将触发此事件。

SystemIdleTimerStart 方法用于开始跟踪空闲时间。 还有一个 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 类才能触发 OnEnterIdleStateOnExitIdleState 事件。

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 属性。

MaxIdleTime property

然后,定义需要在 OnEnterIdleStateOnExitIdleState 事件上执行的代码。

Events on SystemIdleTimer compoenent

并且在您的代码中的某个位置,使用其 Start 方法启动 SystemIdleTimer 组件。 例如

Private Sub Form1_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        SystemIdleTimer1.Start()
End Sub

就这样了。 希望这篇文章对您有所帮助。

© . All rights reserved.