ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 如何处理实现IDisposable的类中的委托/事件引用

2019-06-25 18:56:12  阅读:258  来源: 互联网

标签:c net events idisposable delegates


我一直在阅读关于内存管理的内容,并且在一个项目中遇到过这样的情况,在这个项目中,Google和Google都没有提出确切的答案.我已经知道委托是管理对象,事件是委托实例.话虽如此,一旦应用程序结束,代理实例将从内存中删除.

我无法弄清楚的是如何确保外部代码在我的类处理时(显式地或通过GC)释放所有事件引用.例如,A类公开一个事件而B类使用它. B类在A类上调用Dispose而不释放对代理的引用.当然,我们不能从Dispose方法本身抛出错误.

以下是一个带有委托的类和另一个使用它的类.

public class ClassB
{
    private ClassA A { get; set; }

    public ClassB()
    {
        this.A = new ClassA();
        this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
    }

    public void Process()
    {
        this.A.Process();
    }

    public void ClassA_Processed (ClassA sender, EventArgs e)
    {
        // Do something.

        // Code written by another developer does not free up events before calling Dispose.

        this.A.Dispose();
        this.A = null;
    }
}

public class ClassA: IDisposable
{
    public delegate void DelegateProcessed (A sender, EventArgs e);
    public event DelegateProcessed OnProcessed = null;

    ~ClassA() { this.Dispose(false); }

    public void Dispose ()
    {
        this.Dispose(true);
        System.GC.SuppressFinalize(this);
    }

    private void Dispose (bool disposing)
    {
        if (!this.Disposed)
        {
            if (disposing)
            {
                // Dispose managed resources here.
                // Is it possible / advisable to dispose of delegates / events here?
                // Will this adversely affect the consumer class?
                this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
            }
        }
        this.Disposed = true;
    }

    public void Process () { this.OnProcessed(this, new EventArgs()); }

    public void ClassA_Processed (ClassA sender, EventArgs e) { }
}

重点是确保无论开发人员使用ClassB做什么,ClassA都有资格进行垃圾收集.关键是尽量减少ClassA在内存中花费的时间,即使消费者不小心.

更新:从答案中可以清楚地看出,事件不必从ClassA中明确删除.至于主要问题,弱参考似乎是下面回答的方式.目标是最小化ClassA在内存中停留的时间.如果我忽视了任何事情,请告诉我.

解决方法:

而不是“经典”事件订阅,你应该看看Weak Event Patterns.

事件订阅可以使对象保持活动状态,即使这些引用是唯一的引用,并且引用的对象本身已经超出范围.在这种情况下,引用的对象永远不会被GarbageCollector收集并保持活动直到应用程序结束.

这会导致严重的内存泄漏.

如果您使用的是弱事件模式,则允许GabageCollector更好地确定对象是否仍被引用,或者事件是否是唯一的引用.在这种情况下,会收集对象并释放资源.

标签:c,net,events,idisposable,delegates
来源: https://codeday.me/bug/20190625/1288362.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有