I am developing a custom control, which internally subscribes to Touch.FrameReported - a static event. This has the potential to cause a memory leak (and in some case, it does).
This is my current solution. To subscribe / unsubscribe in the Loaded / Unloaded event. However, I'm finding that the Unloaded event is not always called. This can lead to memory leaks.
// 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;
};
}
Is there a known pattern to solve this? Unsubscribing to events in a Custom Control 'tear-down'? I have already tried:
tl;dr If you use a combination of #1 (unsubscribe on unload) and #3 (weak event listener), then I don't think that your control should be at fault for any memory leaks. There is nothing more you can do.
Implementing IDisposable
doesn't really help, because no-one wants to call "Dispose" on UI elements, and anyway, in those instances where "Unloaded" isn't getting called, requiring "Dispose" would just kick the can down the road. And you're right, the finalizer would not be called if there is a static event holding on to your control as part of its invocation list.
My understanding is that "Unloaded" should be called when your control is removed from the Visual Tree. So in cases where "Unloaded" is not triggered where it definitely should have been, then either there is a bug in a framework control somewhere (which does seem to be a possibility), or there is a bug in your users' code that is preventing your control's container from being unloaded. In either case, your control would not be the source of the memory leak.
Using a weak event handler is probably a good fail-safe -- it allows your control to be GC'd if the only references to it are weak event listeners (hence, this would prevent your "FrameReported" listener from causing a memory leak). I understand your point about implementations -- it seems very tricky to implement, but there is nothing wrong with the technique in principle (as you probably know, the framework uses it as the event listener for bindings).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With