Dr.*_*ABT 6 c# wpf events memory-leaks windows-runtime
我正在开发一个自定义控件,它在内部订阅 Touch.FrameReported - 一个静态事件。这有可能导致内存泄漏(在某些情况下确实如此)。
这是我目前的解决方案。在加载/卸载事件中订阅/取消订阅。但是,我发现 Unloaded 事件并不总是被调用。这可能会导致内存泄漏。
// Imagine this is a CustomControl, to be consumed by users
// with no regard for calling Dispose
public class CustomGrid : Grid
{
public CustomGrid()
{
Loaded += (s, a) =>
{
Touch.FrameReported -= OnTouchFrameReported;
Touch.FrameReported += OnTouchFrameReported;
};
Unloaded += (s, a) =>
{
// The intention is to unsubscribe on unload, which should pre-date
// user intended 'disposal' of the control
Touch.FrameReported -= OnTouchFrameReported;
};
}
Run Code Online (Sandbox Code Playgroud)
有没有已知的模式来解决这个问题?取消订阅自定义控件“拆卸”中的事件?我已经尝试过:
tl;dr 如果您使用#1(卸载时取消订阅)和#3(弱事件侦听器)的组合,那么我认为您的控件不应该因任何内存泄漏而出错。您无能为力。
实现IDisposable并没有真正的帮助,因为没有人愿意在 UI 元素上调用“Dispose”,而且无论如何,在没有调用“Unloaded”的情况下,要求“Dispose”只会把罐子踢到一边。你是对的,如果有一个静态事件保留你的控件作为其调用列表的一部分,则不会调用终结器。
我的理解是,当您的控件从可视化树中删除时,应该调用“Unloaded”。因此,如果“已卸载”没有在绝对应该触发的地方触发,那么要么是某个地方的框架控件存在错误(这似乎确实是一种可能性),要么是您的用户代码中存在错误防止控件的容器被卸载。无论哪种情况,您的控件都不会成为内存泄漏的根源。
使用弱事件处理程序可能是一个很好的故障安全措施——如果对它的唯一引用是弱事件侦听器,它允许您的控件被GC(因此,这将防止您的“FrameReported”侦听器导致内存泄漏) 。我理解您关于实现的观点——实现起来似乎非常棘手,但原则上该技术没有任何问题(您可能知道,框架使用它作为绑定的事件侦听器)。
| 归档时间: |
|
| 查看次数: |
1125 次 |
| 最近记录: |