1

我目前正在研究一个将在一定数量的非活动时间内注销用户的方法。我宣布 Application.Idle

Private Sub Application_Idle(sender As Object, e As EventArgs)
    Timer.Interval = My.Settings.LockOutTime
    Timer.Start()
End Sub

然后,在表单加载事件中调用它

Private Sub ctlManagePw_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    AddHandler System.Windows.Forms.Application.Idle, AddressOf Application_Idle
End Sub

在计时器上

Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer.Tick
    Try
        If My.Settings.TrayIcon = 1 Then
            Me.ParentForm.Controls.Remove(Me)
            control_acPasswords()
            _Main.NotifyIcon.Visible = True
            _Main.NotifyIcon.ShowBalloonTip(1, "WinVault", "You've been locked out due to innactivity", ToolTipIcon.Info)
        End If
        'Stop
        Timer.Stop()
        Timer.Enabled = False
        'Flush memory
        FlushMemory()
    Catch ex As Exception
        'Error is trapped. LOL
        Dim err = ex.Message
    End Try
End Sub

这样做的问题是,每当空闲事件结束时,我仍然会收到通知说我再次被锁定和/或应用程序已进入空闲事件。

control_acPasswords()是注销用户控件

这是我释放内存的地方

Declare Function SetProcessWorkingSetSize Lib "kernel32.dll" (ByVal process As IntPtr, ByVal minimumWorkingSetSize As Integer, ByVal maximumWorkingSetSize As Integer) As Integer
Public Sub FlushMemory()
    Try
        GC.Collect()
        GC.WaitForPendingFinalizers()
        If (Environment.OSVersion.Platform = PlatformID.Win32NT) Then
            SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1)
            Dim myProcesses As Process() = Process.GetProcessesByName(Application.ProductName)
            Dim myProcess As Process
            For Each myProcess In myProcesses
                SetProcessWorkingSetSize(myProcess.Handle, -1, -1)
            Next myProcess
        End If
    Catch ex As Exception
        Dim err = ex.Message
    End Try
End Sub

如果我放置一个MsgBox(ex.Message)Timer_Tick 事件异常,我会不断收到

Object reference not set to an instance of an object

我的预期结果是,每当表单进入 Idle 事件时,它将获取间隔或时间,My.Settings.LockOutTime其中是分钟值并存储为60000for 1 minuteor60 seconds并启动计时器。现在在 Timer_Tick 上logout,如果间隔结束,则用户。

我处理事件的方式有什么问题吗?

4

2 回答 2

3

Application.Idle 事件触发多次。每次 Winforms 从消息队列中检索所有消息并将其清空。问题是,它触发的第二次和后续时间,您正在启动一个已经启动的计时器。这没有任何效果,您必须将其重置,以便在编程的时间间隔内再次开始滴答作响。容易做到:

Private Sub Application_Idle(sender As Object, e As EventArgs)
    Timer.Interval = My.Settings.LockOutTime
    Timer.Stop()
    Timer.Start()
End Sub

下一个问题(可能是异常的原因)是您必须在表单关闭时明确取消订阅该事件。它不是自动的,Application.Idle 是一个静态事件。使用 FormClosed 事件:

Protected Overrides Sub OnFormClosed(ByVal e As System.Windows.Forms.FormClosedEventArgs)
    Timer.Stop()
    RemoveHandler Application.Idle, AddressOf Application_Idle
    MyBase.OnFormClosed(e)
End Sub
于 2012-09-20T10:50:49.047 回答
2

除了汉斯的回答:当用户不再空闲时,您似乎没有停止计时器的运行。也就是说,定时器在我空闲时启动,但如果我回来,当定时器滴答作响时,我仍然会被锁定。

您需要确保在用户再次激活时停止计时器。

于 2012-09-20T10:55:46.113 回答