在C#中,Do事件是否保留对回调方法所在的整个类的引用?

mik*_*010 1 .net c# memory memory-leaks memory-management

我有一个将ConcurrentDictionary作为私有成员的类.该类还定义了委托/回调方法.基类将此方法注册为外部事件的回调.这只是一个ONCE.

我正在运行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));

    }
}
Run Code Online (Sandbox Code Playgroud)

这是在上面提到的基类的子类中实现的处理程序:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

publishData方法发布prism事件

age*_*t-j 5

这是怎么回事

是的,事件是一个代表列表,它有两个相关的字段:targetmethod.除非您引用静态方法,否则是对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; }
  }
Run Code Online (Sandbox Code Playgroud)

这将帮助您找到为什么订阅这么多次.