更新:我wrote a program测试下面提到的每种技术的内存含义。毫不奇怪,我发现,确实可以肯定,使用.NET事件的常规方法会比其他方法创建更多的垃圾(这意味着,它实际上确实在创建垃圾,这与其他两个似乎都没有创建的策略相反)任何垃圾)。
确实,我应该一直强调,我对.NET事件中TEventArgs
参数的内存开销比对速度的开销更感兴趣。最终,我不得不承认,就所有实际目的而言(就内存和速度而言),成本都是可以忽略的。不过,我认为有趣的是,以“常规”方式引发许多事件确实会花费一些钱,而且在极端情况下,它甚至可能导致第1代垃圾回收,这可能会或可能不会很重要,具体取决于情况(根据我的经验,系统需要越“实时”,更重要的是要牢记在何处创建垃圾以及如何在适当的地方将其最小化)。
这似乎是一个愚蠢的问题。我意识到,例如Windows窗体很容易被认为是“高性能”方案,无休止地连续引发数百甚至数千个事件(例如Control.MouseMove
事件)。但是,我仍然想知道,如果期望使用高性能,时间紧迫的代码来设计具有.NET事件的类,是否真的合理?
我主要关心的是一种约定,即对所有事件都使用EventHandler<TEventArgs>
之类的东西,其中TEventArgs
源自EventArgs
,并且很可能是每次引发/处理事件时都必须实例化的类。 (显然,如果只是普通的EventsArgs
,则不是这种情况,因为可以使用EventArgs.Empty
;但是假设TEventArgs
类型包含任何有意义且非常量的信息,则可能需要实例化。)似乎这样会导致更大的结果。 GC的压力超出了我创建高性能库的期望。
也就是说,我能想到的唯一替代方法是:
EventHandler<TEventArgs>
),仅采用不需要对象实例化的参数,例如int
,double
等(甚至是string
,并将引用传递给现有字符串对象)。 我对.NET事件的GC压力的担心是否毫无根据?如果是这样,我在那里想念什么?或者,是否有第三种选择比我刚才列出的两种更好?
最佳答案
在执行任何操作之前,您应该考虑进行某种程度的性能分析,以确保这实际上会带来一个实际的问题。 在诸如UI鼠标移动的情况下,事件发生的频率比机器低,因此对GC行为的影响通常可以忽略不计。请记住,.NET GC非常擅长收集很少引用的短期对象-它是在许多地方引用的中长期对象,这可能会造成问题。
但是,如果(出于某种原因)确实通过一个问题证明了这一点,则有两种可能的方法可以降低成本。