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

标签 c# .net memory memory-management memory-leaks

我有一个以 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)列表,它有两个相关字段: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; }
  }

这将帮助您找到为什么它被订阅了这么多次。

关于c# - 在C#中,事件是否保留对回调方法所在的整个类的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10853300/

相关文章:

C# + GL 控制混合背景与窗体

c# - 如何使用 JavaScript 解密 AesCryptoServiceProvider?

.net - 交叉类型 LINQ

c# - 使用 C#/LINQ 注入(inject)/合并嵌套数组

c# - 根据列和值在dataGridView中查找一行

c# - Gui 异步操作模式?

memory - 为什么在CNN中用GEMM的im2col的方法比用SIMD的方向实现的方法效率更高

c# - 获取内存中 DataTable 或 ArrayList 的大小

ios - 全局常量中的内存使用更少

c# - 谷歌云 API 语法