你如何找到在C#中订阅活动的内容?

时间:2010-12-09 15:55:22

标签: c# debugging events

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

我们通过抽奖的运气获得了一些双重订阅错误,但应用程序确实将事件用于许多事情。虽然我们非常清楚取消订阅您订阅的所有内容的原则,但仍然存在内存泄漏。我想系统地确定订阅什么。

修改

感谢您指向GetInvocationList()方法的指针。我正在尝试创建一个动态转储结果的调试工具。问题是我发现的解决方案在.Net 2中工作,但不再在.Net 3.5中。本质上,告诉您获取EventInfo的相应FieldInfo(分别为反射,GetField和GetEvents)。但是,在.Net 3.5中没有相应的FieldInfo,EventInfo也不会让我获得调用列表。

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

3 个答案:

答案 0 :(得分:6)

尝试在名为event的{​​{1}}上使用方法。

这将返回订阅该事件的一组代表。

数组将按照添加的顺序包含代理。这也可以用来从列表中单独输出和调用特定的委托,而调用GetInvocationList方法将调用它们(但只给你最后一个委托的返回值)

答案 1 :(得分:1)

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

解决这个问题的另一种方法是从出版商的角度出发。将所有订阅者都放到UNsubscribe可能不方便,但如果发布者需要被销毁/超出范围,则可以触发将其所有事件设置为null - 有效取消订阅所有人并打破循环。

如果发布者具有更长的生命周期并且保持其他对象存活,则可能必须执行之前建议的GetInvocationList。但我认为这只是为了调试问题 - 找出谁不应该挂在事件上。

您可以考虑使用一些基于WeakReferenced的自定义事件订阅机制。

答案 2 :(得分:0)

请参阅this blog post,了解在Watch窗口中查看事件订阅者的有用转储的简洁方法。