我有一个以 ConcurrentDictionary 作为私有(private)成员的类。 此类还定义了委托(delegate)/回调方法。 基类将此方法注册为外部事件的回调。这是一个只有一次。
我正在运行 ANT 内存分析器,我看到从数百个 ConcurrentDictionary 属性实例引用了 1000 个 MyObj 实例。这些的 GC 根是事件回调。
这似乎导致内存在应用程序运行时显着增加。大约 5 分钟后,大部分内存被回收,但我担心该应用程序可能会遇到问题,因为它在 GC 开始之前,它会迅速膨胀并持续很长时间。
这是怎么回事,我该如何解决?
这是注册处理程序的基本调用片段
protected abstract void DataReceivedEventHandler(DataChangedEvent evt);
public virtual void RegisterForChanges(ICollection<MemoryTable> tables)
{
foreach (MemoryTable table in tables)
{
_subscribedTables.Add(table);
table.RegisterEventListener(new DataChangedCallBack(this.DataReceivedEventHandler));
}
}
这是在上述基类的子类中实现的处理程序:
private ConcurrentDictionary<string, DataRecord> _cachedRecords;
protected override void DataReceivedEventHandler(DataChangedEvent evt)
{
DataRecord record = evt.Record as DataRecord;
string key = record.Key;
if (string.IsNullOrEmpty(key)) { return; }
if (_cachedRecords.ContainsKey(key))
{
_cachedRecords[key] = record;
DateTime updateTime = record.UpdateTime;
TimeSpan delta = updateTime - _lastNotifyTime;
if (delta.TotalMilliseconds > _notificationFrequency)
{
PublishData(updateTime);
}
}
}
publishData方法发布棱镜事件
最佳答案
发生了什么
是的,事件是一个委托(delegate)列表,它有两个相关字段:target
和method
。除非您引用静态方法,否则 target
是对该类的引用。 method
是一个反射 MemberInfo
,它告诉事件调用哪个方法。
如何排除故障
考虑在 add_EventName
方法中放置一个断点。 (如果您没有明确的 add_EventName 和 remove_EventName,则必须使用此明确代码重新定义您的事件)。
private event EventHandler eventName;
public event EventHandler EventName
{
add { eventName += value; } // Breakpoint here
remove { eventName -= value; }
}
这将帮助您找到为什么它被订阅了这么多次。
关于c# - 在C#中,事件是否保留对回调方法所在的整个类的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10853300/