我们考虑使用 Prism 事件聚合器来减少由于以下原因导致的内存泄漏事件参考。
-
这本身就是使用此模式的正当理由吗?其他好处现在对我们来说并不感兴趣。我们计划在模型组件之间使用它,而不是 UI。
-
我们的问题是一些开发人员忘记取消注册事件。我看到 Prism 有一种使用弱引用的风格,但它有 限制。另一种风格强制显式取消订阅(),这又可能会被忘记。那么如何更好呢?
We consider to use the Prism event aggregator for the purpose of reducing memory leaks due to event references.
-
Is this for itself a valid reason to use this pattern? The other benefits are not interesting for us now. We plan to use it between model components and not UI.
-
Our problem was that some developers forgot to unregister events. I saw that Prism has one flavour which uses weak references but it has limitations. The other flavour forces to explicitly Unsubscribe(), which again can be forgotten. So how is it better?
发布评论
评论(1)
如果这是您的问题,那么切换到 Prism 事件聚合器(或使用任何其他实现)不会改善情况。
在混乱的情况下添加一个新的依赖项和一个新的、重要的使用模式根本不会把它整理好。
您需要是清理代码。
我建议不要使用新的代码库,而是研究静态分析工具,例如 fxCop (又名代码分析)、宪兵 和 NDepend。所有这些都能够检测到一些事件未脱钩或 IDisposable 未正确实现的情况。
使用静态分析,您可以冷静地识别需要清理的代码。使用内存分析器(例如 dotTrace Memory),您将能够找到最差的内存违者并及时清理。
更新
回答下面评论中的问题:
可能很难确保所有事件都被取消订阅 - 但考虑到事件的实现方式(请参阅通过 C# 的 CLR< /a> 了解详细信息),您可以通过确保丢弃所有事件订阅来进行一些作弊。
不要
自己处理事件订阅,如下所示:
然后,在您的类上实现
IDisposable
,并在您的Dispose()
方法中将mFuBar
设置为null
,放弃订阅。然后,FxCop(和其他工具)可以告诉您是否无法处理该类。If this is your problem, switching to the Prism event aggregator (or, using any other implementation) won't improve things.
Adding a new dependency with a new, non-trivial, usage pattern into a messy situation isn't going to tidy it up at all.
What you need is to clean up your code.
Instead of new code libraries, I'd suggest looking into static analysis tools like fxCop (aka Code Analysis), Gendarme and NDepend. All of these are able to detect some situations where events are not unhooked or where IDisposable is not implemented properly.
Using static analysis, you can dispassionately identify code that needs cleanup. Throw in use of a memory profiler (like dotTrace Memory) and you'll be able to find the worst offenders and clean them up promptly.
Update
In answer to the question in the comment below:
In can be difficult to make sure that all events are unsubscribed - but given the way that events are implemented (see CLR via C# for details), you can cheat a little by ensuring all event subscriptions are discarded.
Instead of
handle the event subscription yourself, like this:
Then, implement
IDisposable
on your class, and in yourDispose()
method setmFuBar
tonull
, discarding the subscriptions. FxCop (and other tools) can then tell you if you are failing to Dispose of the class.