每次触发事件时是否都必须实例化一个新的自定义eventarg?

时间:2018-09-29 14:37:36

标签: vb.net winforms visual-studio-2017 mono raspberry-pi3

我有一个WinForms应用程序,该应用程序使用带有自定义eventargs的事件来更新MainForm上的状态面板。

我在课堂上声明自己的事件,如下所示:

Public Event BomNotLoaded As EventHandler(Of StatusEventArgs)

事件触发时,我这样称呼它:

OnBomNotLoaded(New StatusEventArgs(2, "Please scan a SKU/UPC First!", Color.Red, Color.White))

Protected Overridable Sub OnBomNotLoaded(ByVal e As StatusEventArgs)
    RaiseEvent BomNotLoaded(Me, e)
End Sub

在MainForm代码中,我有这个:

Private Sub _station_BomNotLoaded(sender As Object, e As StatusEventArgs) Handles _station.BomNotLoaded
    SetStatus(e)
    _alert.InvalidScan()
End Sub

然后,SetStatus方法使用StatusEventArgs中的值来设置标签文本,图像,标签背景色和标签文本颜色。该图像是从第一个数字得出的代码编号。

我是否有必要在每次触发此事件时实例化一个新的StatusEventArgs?还有另一种方法可以提供更好的性能吗?

我问的原因是该应用程序在Mono下的RaspberryPi3上运行,并且我遇到了CPU使用率较高的性能问题。

1 个答案:

答案 0 :(得分:0)

实际上,将一个对象创建为初始化对象并进行修改,然后将其传递给每个事件调用,应该没有什么坏处。引发事件时,该事件将创建并发送指向EventArgs对象的指针的副本。毕竟,事件Args是一个ByVal声明。在标准行为中,将创建EventArgs对象,然后将其丢弃。在这种情况下,经过几个周期,实际上在内存中有2个对EventArgs对象的引用。各种特性的重量始终保持不变,尽管仅在需要使用时相反。这也有可能使eventargs实例在被事件处理程序使用之前被调用代码修改。

现在,对于改变行为,有一些选择,而选择意味着选择,优点和缺点。

第一个是坏建议,但可行。如果在使用前在事件处理程序中检查事件对象是否为NOTHING,则可以在eventargs为空的情况下引发事件。但这是一个不好的设计范例,因为这是意外的。我们假设EventArgs对象将是某种东西。

Private Sub _station_BomNotLoaded(sender As Object, e As StatusEventArgs) Handles _station.BomNotLoaded
   If e IsNot Nothing Then 
      SetStatus(e)
      _alert.InvalidScan()
   End If 
End Sub

就像我说的那样,我认为这是一个坏主意,因为它的行为方式出乎意料。

或者,如果您修改/创建所需的事件,那么您将描述每个事件的事件签名。

如果添加的事件(例如“ BomNotScanned”)没有与之关联的Event自变量类,则可以引发该事件,并且在未扫描SKU / UPC的特定情况下可以处理该事件。然后,您仍然可以将BomNotLoaded用于数据不符合预期的其他情况。

这具有使事件结构更加复杂的缺点。在某些情况下是预期的,在其他情况下则不是。

另一种可能性是,在数据与预期不符的情况下(例如,未扫描SKU / UPC)引发异常,仅在数据为“良好”的情况下使用事件。在那种情况下,使用代码在函数中内联处理它,而不是在其他地方弹出事件。这样做的缺点是,异常包括堆栈信息,并且在性能方面比事件要重。

最后,您在当前的操作方式中有几种选择会以较小的方式影响性能。

首先,是将事件状态的上下文线索从对象传递到表单。您的StatusEventArg具有这4个参数,其中两个是颜色,我假设您将其用于警报消息。我首先假设的是某种类型的标识标志。

IMO,您应该根据识别标志使UI标志具有这些颜色(即2给您红色背景,白色文本为粗体,而1则在白色背景上以正常重量显示黑色文本,等等) 。这就造成了关注点的分离,并阻止了扫描程序类指示主表单如何响应事物。

同样,删除描述字符串代替定义的枚举标志意味着您来回传递的信息较少,从而提高了效率。这意味着,您只发送一个整数,而不是从类向表单发送3个整数和一个字符串。

最后,您可以为StatusEventArgs构建NEW方法,以便它不接受参数,而仅定义某个基本状态(例如,良好状态)。然后,您可以使用WITH(作为对象初始化程序)来设置任何给定方案所需的参数。

例如,考虑此类的定义:

Public class StatusEventArgs
   Inherits EventArgs 

   Public Sub New()
     Flag = 1 
     Random1 = "Random Text" 
     Random2 = ""
   End Sub 

   Public Property Flag AS Integer 
   Public Property Random1 As String
   Public Property Random2 As String 
End Class

然后我可以通过以下方式实例化它:

Dim se1 As new StatusEventArgs With {.Flag = 2, .Random1="Bob Denver"} 
Dim se2 As New StatusEventArgs With {.Random1 = "Hello", .Random2="World" }

实际上,这并不能真正为您节省任何性能,但这确实意味着您只需要在要更改默认值的地方进行值定义。

所有这些,我不确定所定义逻辑的任何方面都会引起性能问题,除非您经常提出该事件。就是说,我对Raspberry PI等嵌入式系统不太熟悉。