检测一系列变量是否已更改的事件 [英] Event that detects whether a series of variables have changed

查看:55
本文介绍了检测一系列变量是否已更改的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个程序来监视外部进程的输出。我有一个计时器设置,每次打勾都会从外部进程请求数据,结果存储在我的班级中。如果任何变量已从之前的状态更改,我想更新数据库中的结果。我已经设置了一个模拟这个的测试程序,但规模要小得多。现在,我只检查3个变量。我设置了一个包含3个变量结果的类,并为每个变量创建了属性。在每个属性中,我调用一个在变量更改值时触发的事件。



然后我创建了一个处理所有3个事件的事件处理程序。如果触发了其中一个事件,则会更新我的数据库。这一切都很好,除了一件事。如果单个变量已更改,则它会更新数据库中的变量。如果2个变量同时发生变化,则事件将触发两次,这将使数据库更新2次。如果所有3个变量同时发生变化,那么它将更新数据库3次。我想避免使数据库负担过重,所以我不想在每个计时器滴答时多次更新它,无论一个变量或所有变量是否发生变化。怎么能最好地处理?我唯一能想到的是创建一个变量和一个包含数组,列表或类似内容的所有3个结果的属性。这是我最好的选择还是还有其他我想念的东西?



我尝试了什么:



I am creating a program that will monitor the output of an external process. I have a timer setup that requests data from the external process every tick and the results are stored in my class. If any of the variables have changed from their previous state, I want to update the results in a database. I have setup a test program that simulates this but on a much smaller scale. For now, I am only checking 3 variables. I have setup a class that holds the results of the 3 variables and I have created properties for each variable. In each property, I call an event that gets triggered when the variable changes value.

I have then created an event handler that handles all 3 events. If one of the events is triggered, it updates my database. This all works fine except for one thing. If a single variable has changed, then it updates the variable in the database just fine. If 2 variables change at the same time, then the event fires twice which will update the database 2 times. If all 3 variables change at the same time, then it will update the database 3 times. I want to avoid overtaxing the database so I don’t want to update it more than once every timer tick no matter if one variable or all variables change. How can this best be handled? The only thing that I can think of is to create one variable and one property that contains all 3 results in either an array, list or something similar. Is this my best option or is there something else I am missing?

What I have tried:

Public Class ClassTimerVars

    Private _Feedrate As Integer
    Public Event FeedrateChanged()
    Private _Spindle As Integer
    Public Event SpindleChanged()
    Private _Rapid As Integer
    Public Event RapidChanged()
   


    Public Property Feedrate() As Integer
        Get
            Feedrate = _Feedrate
        End Get
        Set(ByVal value As Integer)
            If _Feedrate <> value Then
                _Feedrate = value
                RaiseEvent FeedrateChanged()
            End If
        End Set
    End Property

    Public Property Spindle() As Integer
        Get
            Spindle = _Spindle
        End Get
        Set(ByVal value As Integer)
            If _Spindle <> value Then
                _Spindle = value
                RaiseEvent SpindleChanged()
            End If
        End Set
    End Property

    Public Property Rapid() As Integer
        Get
            Rapid = _Rapid
        End Get
        Set(ByVal value As Integer)
            If _Rapid <> value Then
                _Rapid = value
                RaiseEvent RapidChanged()
            End If
        End Set
    End Property

End Class







Public Class Form1

    Private TimerTick As Long = 0
    Private WithEvents test As New ClassTimerVars
    Private EventsFired As Long = 0


    Private Sub OverrideChanged() Handles test.FeedrateChanged, test.SpindleChanged, test.RapidChanged

        Me.TxtFeedrate.Text = test.Feedrate
        Me.TxtSpindle.Text = test.Spindle
        Me.TxtRapid.Text = test.Rapid

        EventsFired += 1
        Me.LblEventsFired.Text = "Events Fired = " & EventsFired

        'Update the Database here

    End Sub

    Private Sub BtnStartTimer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStartTimer.Click
        Timer1.Start()
    End Sub

    Private Sub BtnStopTimer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStopTimer.Click
        Timer1.Stop()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        'Simulate Extracting data from an external process
        'Update the 3 variables on different intervals to see how many times the event is triggered

        TimerTick += 1

        'Update Feedrate in the class
        If TimerTick Mod 2 = 0 Then
            test.Feedrate = TimerTick
        End If

        If TimerTick Mod 4 = 0 Then
            test.Spindle = TimerTick
        End If

        If TimerTick Mod 8 = 0 Then
            test.Rapid = TimerTick
        End If


    End Sub
End Class

推荐答案

作为NotPolitcallyCorrect [ ^ ]在问题的评论中提到,你必须使用 EventArgs类(系统) [ ^ ]。在相关页面的底部你会找到一个例子。





这是一个使用您的类的代码示例:

As NotPolitcallyCorrect[^] mentioned in the comment to the question, you have to use EventArgs Class (System)[^]. At the bottom of related page you'll find an example.


Here is a code sample which uses your class:
'methods and classes

Public Sub ctv_DataHasBeenAdded(sender As Object, e As ClassTimerVarsEventArgs)
	Console.WriteLine("New data has been added! Feedrate: {0}, Spindle: {1}, Rapid: {2}.", e.Feedrate, e.Spindle, e.Rapid)
	Dim c As ClassTimerVars = DirectCast(sender, ClassTimerVars)
	Console.WriteLine(c.ToString())
End Sub

Public Class ClassTimerVars
    Private _Feedrate As Integer
    Private _Spindle As Integer
    Private _Rapid As Integer

  	Public Sub New()
		'default constructor	
	End Sub
	
	Public Sub New(iFeedrate As Integer, iSpindle As Integer, iRapid As Integer)
    	_Feedrate = iFeedrate
    	_Spindle = iSpindle
    	_Rapid = iRapid
    End Sub

    Public Property Feedrate() As Integer
        Get
            Feedrate = _Feedrate
        End Get
        Set(ByVal value As Integer)
            _Feedrate = value
        End Set
    End Property

    Public Property Spindle() As Integer
        Get
            Spindle = _Spindle
        End Get
        Set(ByVal value As Integer)
            _Spindle = value
        End Set
    End Property

    Public Property Rapid() As Integer
        Get
            Rapid = _Rapid
        End Get
        Set(ByVal value As Integer)
            _Rapid = value
        End Set
    End Property

	Public Overrides Function ToString() As String
		Return String.Format("ClassTimerVars totals - Feedrate: {0}, Spindle: {1}, Rapid: {2}.", _Feedrate, _Spindle, _Rapid)
	End Function

    Public Sub AddData(ByVal iFeedrate As Integer, ByVal iSpindle As Integer, ByVal iRapid As Integer)
            _Feedrate += iFeedrate
            _Spindle += iSpindle
			_Rapid += iRapid
			Dim args As ClassTimerVarsEventArgs = New ClassTimerVarsEventArgs() _
				With {.Feedrate = iFeedrate, .Spindle = iSpindle, .Rapid = iRapid}
            OnDataAdded(args)
    End Sub

    Protected Overridable Sub OnDataAdded(e As ClassTimerVarsEventArgs)
        RaiseEvent DataHasBeenAdded(Me, e)
    End Sub

    Public Event DataHasBeenAdded As EventHandler(Of ClassTimerVarsEventArgs)

End Class

Public Class ClassTimerVarsEventArgs
	Inherits EventArgs

    Public Property Feedrate As Integer
    Public Property Spindle As Integer
    Public Property Rapid As Integer

End Class



用法:


Usage:

Sub Main
	'create new instance of ClassTimerVars with initial values
	Dim ctv As ClassTimerVars = New ClassTimerVars(1,5,10)
	AddHandler ctv.DataHasBeenAdded, AddressOf ctv_DataHasBeenAdded
	
	'dispplay initial value
	Console.WriteLine(ctv.ToString())
	'add data #1
	ctv.AddData(2,8,11)	
	'add data #2
	ctv.AddData(Nothing,3,21)
	'add data #3
	ctv.AddData(12,4,Nothing)
	
End Sub





输出:



Output:

ClassTimerVars totals - Feedrate: 1, Spindle: 5, Rapid: 10.
New data has been added! Feedrate: 2, Spindle: 8, Rapid: 11.
ClassTimerVars totals - Feedrate: 3, Spindle: 13, Rapid: 21.
New data has been added! Feedrate: 0, Spindle: 3, Rapid: 21.
ClassTimerVars totals - Feedrate: 3, Spindle: 16, Rapid: 42.
New data has been added! Feedrate: 12, Spindle: 4, Rapid: 0.
ClassTimerVars totals - Feedrate: 15, Spindle: 20, Rapid: 42.





尝试!



Try!


使用计时器轮询变量将丢失事件。这需要经典的观察者模式 [ ^ ]。
Polling variables with a Timer will miss events. This requires the classic Observer Pattern[^].


我会做一些类似于评论中描述的内容:

你为你的班级制作一个活动,每次房产改变时都会被激活。



如果你想建立自己的List(ClassTimerVars),你会覆盖Add-Method并在此处重定向来自您的类的事件来自List(AddHandler)的自己的事件。

如果从这些列表中删除一个项目(或处置它),您应该删除处理程序List-Method的Class-Item。
I would do something like described in the Comments :
you make one Event for your class which is fired every time a property changes.

If you want to build your own List (of ClassTimerVars) you override the Add-Method and redirect here the Event from your class the an own Event from your List (AddHandler).
If you remove an Item from those List (or dispose it) you should remove the Handler from the Class-Item to the List-Method.


这篇关于检测一系列变量是否已更改的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆