你如何知道在C#中订阅了哪些活动?

你如何知道在C#中订阅了哪些活动?,c#,debugging,events,C#,Debugging,Events,我遇到了一个问题,我正在处理的应用程序内存泄漏。经验告诉我,垃圾收集语言最早经历内存泄漏的地方之一是处理订阅事件和以后无法取消订阅事件。第二个与存储静态状态有关。我是C#的新手,对不透明的事件类型感到沮丧 通过抽奖的运气,我们发现了一些双重订阅错误,但应用程序确实在很多方面使用了事件。虽然我们很清楚取消订阅所有订阅内容的原则,但仍然存在内存泄漏。我想系统地确定订阅什么 编辑: 感谢您提供了指向GetInvocationList()方法的指针。我正在尝试创建一个调试工具,它将动态转储结果。问题是我

我遇到了一个问题,我正在处理的应用程序内存泄漏。经验告诉我,垃圾收集语言最早经历内存泄漏的地方之一是处理订阅事件和以后无法取消订阅事件。第二个与存储静态状态有关。我是C#的新手,对不透明的事件类型感到沮丧

通过抽奖的运气,我们发现了一些双重订阅错误,但应用程序确实在很多方面使用了事件。虽然我们很清楚取消订阅所有订阅内容的原则,但仍然存在内存泄漏。我想系统地确定订阅什么

编辑:

感谢您提供了指向
GetInvocationList()
方法的指针。我正在尝试创建一个调试工具,它将动态转储结果。问题是我发现的解决方案在.NET2中有效,但在.NET3.5中不再有效。本质上,函数告诉您获取EventInfo对应的FieldInfo(分别是reflection、GetField和GetEvents)。然而,在.NET3.5中没有相应的FieldInfo,EventInfo不允许我获取调用列表


我只想转储事件列表及其调用列表以进行调试。

尝试在
事件上使用名为
GetInvocationList
的方法

这将返回订阅事件的委托数组


数组将按代理添加的顺序包含代理。这也可用于从列表中挑出并调用特定的委托,而调用
事件。Invoke
方法将调用所有委托(但只提供上次调用的委托的返回值)

您怀疑事件订阅是导致内存“泄漏”的原因,这一点肯定是对的。几年前,我们发现了一个问题,即应用程序范围的静态对象订阅ASP.NET页面事件,您可以猜到那里发生了什么

另一种解决方法是从出版商的角度。让所有订阅者取消订阅可能不太方便,但如果需要销毁/超出范围,则可能会触发该发布者,将其所有事件设置为空-有效地取消订阅所有人并打破循环

如果发布者的生命周期较长,并且是使其他对象保持活动状态的因素,那么您可能必须执行前面建议的GetInvocationList操作。但我会认为这只是为了调试问题——找出谁在不应该发生的事情上坚持下去。
最后,你可以考虑一些基于弱引用的自定义事件订阅机制。

参见我的答案,基于C事件的内存泄漏,上个月遇到了类似的问题。我很难选择哪两个应该得到“官方”的答案,因为它们都满足了我不同需要的部分。最后,我选择了一个回答标题中问题的答案,尽管n8wrl的答案在不同方面都一样好。这也是非常有用的。我将了解如何在对象上连接Dispose()方法,以清除侦听器。我仍然需要有效地检查结果。