取消订阅活动 - 性能受到影响?

Bas*_*Bas 19 c# event-handling

请考虑以下代码(来自性能报告):

绩效报告

这是属性通知侦听器组件的一部分.该方法OnItemPropertyChanged是具有PropertyChangedEventHandler签名的私有实例绑定方法.该方法被调用大约100.000次并且导致应用程序中的显着延迟.

是否存在与(un)订阅事件相关的性能考虑因素?有没有解释为什么会导致这样的性能损失?

Mar*_*ell 16

首先要注意的是:

notificationItem.PropertyChanged -= OnItemPropertyChanged;
Run Code Online (Sandbox Code Playgroud)

为此目的实际分配了一个新的代表.它还意味着等价测试不能在身份等同性上短路- 它必须执行方法/目标等价(即不同的委托实例,但是相同的目标/方法,因此被认为是代表组合的等价物).

我会尝试首先将使用一个单一的委托实例,即

void OnItemPropertyChanged(object sender, PropertyChangedEventArgs args) {...}

private readonly PropertyChangedEventHandler sharedHandler;
public YourType() { // constructor
    sharedHandler = OnItemPropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)

然后当您订阅时,而不是:

notificationItem.PropertyChanged += OnItemPropertyChanged;
Run Code Online (Sandbox Code Playgroud)

要么

notificationItem.PropertyChanged -= OnItemPropertyChanged;
Run Code Online (Sandbox Code Playgroud)

改为使用:

notificationItem.PropertyChanged += sharedHandler;
Run Code Online (Sandbox Code Playgroud)

要么

notificationItem.PropertyChanged -= sharedHandler;
Run Code Online (Sandbox Code Playgroud)

值得一试,至少.


Tig*_*ran 14

注意94.2%相对执行时间有关.因此取消订阅占用94.2%Disable(..)方法的总执行时间.考虑到其他代码原始castnull检查,这是正常的.

真正的问题,国际海事组织(即使在性能方面的任何事情都是严格把具体的执行上下文)的是,这个方法被调用100.000倍.


Bas*_*Bas 5

关于许多评论提出的设计缺陷:我们强烈建议用户不要将带有100k对象的对象图放入用户界面; 这是持续改进过程的一部分,希望将来能够得到解决.

传递给unsubscription运算符的引用sharedHandlerMethod引用之间没有显着差异.

使用弱事件管理器类可以消除性能损失; 无论有没有创建像Marc Gravell这样的代表建议.也许这与此类有关,它以不同的方式创建自己的事件侦听器,而不是使用其参数中提供的那个.我特地到,但无法找到一个解释,为什么这种模式似乎工作速度快(因为+=-=运营商仍称).