gpt4 book ai didi

c# - 在 CustomControls 中取消订阅事件的模式

转载 作者:行者123 更新时间:2023-11-30 17:47:12 34 4
gpt4 key购买 nike

我正在开发一个自定义控件,它在内部订阅 Touch.FrameReported - 一个静态事件。这有可能导致内存泄漏(在某些情况下确实如此)。

这是我目前的解决方案。在 Loaded/Unloaded 事件中订阅/取消订阅。但是,我发现并不总是调用 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;
};
}

是否有解决此问题的已知模式?取消订阅自定义控件“拆卸”中的事件?我已经试过了:

  • 取消订阅卸载。并不总是被调用。
  • 处置。无法使用,因为用户可能无法确定性地调用 Dispose
  • Weak Events .不错,但许多实现不适合 WinRT/Silverlight,或者,它们需要显式注销,或者,它们仅在调用事件时注销(Duh!这是一个弱事件)!
  • 终结器。如果有像事件处理程序这样的 GC 根,Finalizer 不会被阻止吗?

最佳答案

tl;dr 如果您结合使用 #1(卸载时取消订阅)和 #3(弱事件监听器),那么我认为您的控件不会因任何内存泄漏而出错。您无能为力。

实现 IDisposable 并没有真正的帮助,因为没有人想在 UI 元素上调用“Dispose”,而且无论如何,在那些没有调用“Unloaded”的情况下,需要“处理”只会把 jar 头踢到路边。你是对的,如果有一个静态事件作为其调用列表的一部分保留在你的控件上,则不会调用终结器。

我的理解是,当您的控件从可视化树中移除时,应该调用“Unloaded”。因此,如果“已卸载”未在绝对应该触发的位置触发,则可能是框架控件某处存在错误 (which does seem to be a possibility),或者您的用户代码中存在阻止您的控件容器的错误从被卸载。无论哪种情况,您的控件都不是内存泄漏的根源。

使用弱事件处理程序可能是一个很好的故障安全 - 如果对它的唯一引用是弱事件监听器,它允许您的控件被 GC(因此,这将防止您的“FrameReported”监听器导致内存泄漏)。我理解您关于实现的观点——实现起来似乎非常棘手,但原则上该技术没有任何问题(您可能知道,框架将其用作绑定(bind)的事件监听器)。

关于c# - 在 CustomControls 中取消订阅事件的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25005355/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com