locked
[UWP][C++] My custom ContentControl won't get GCd if somewhere, something is registered for an event. RRS feed

  • Question

  • Hi,

    I have a custom control for a UWP app, to be used by multiple other projects (i.e. it's part of what results in a winmd file).

    For future reference, let's call it MyControl.

    MyControl derives from the built in ContentControl, and itself contains some child controls (ScrollViewer and more). I have added my own destuctor to the class, but have found that it doesn't always get called. In particular, it seems that if somewhere in my app, some other control is registered for an event on MyControl, and doesn't unregister, then MyControl doesn't get GCd. This happens even if all these controls get completely separated from the rest of my application (not part of the UI tree, no references to either anywhere).

    Is this something others have experienced? Is this expected at all? Are there any good tools for debugging these things?

    Thanks,
    Tomas

    Wednesday, March 15, 2017 8:41 PM

All replies

  • It depends on the specific calling pattern. Usually you shouldn't need to explicitly remove event handlers, but there are some scenarios which can leave things rooted. This is discussed in the Removing event handlers in code section at https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/events-and-routed-events-overview along with the common scenarios where you'd need to explicitly remove events.

    I suspect something in your mix of C++ (mentioned in your subject) and C# (since you mention GC) interop is keeping things live. Visual Studio's memory profiler will let you see the rooting tree for a specific object so you can see what is holding your event handler in memory. See https://blogs.msdn.microsoft.com/visualstudioalm/2015/04/29/diagnosing-event-handler-leaks-with-the-memory-usage-tool-in-visual-studio-2015/ (WPF example, but the concepts are general to any .Net app).

    Also note that garbage collection is indeterminate: it doesn't happen immediately when your controls are removed from the tree. Garbage collection will occur when (and if) the GC system determines that it needs to. If the system isn't starved for memory then it may never occur. If your control manages non-memory resources that need to be cleaned up then look at the Dispose pattern rather than destruction / finalization.

    You can also look into weak event patterns in C# to prevent the event handlers from pinning the objects. There is a WeakEventListener object in the UWP community toolkit at https://developer.microsoft.com/en-us/windows/uwp-community-toolkit/helpers/weakeventlistener .

    --Rob

    Wednesday, March 15, 2017 9:28 PM
  • Thanks Rob,

    I have been trying to follow the guide you posted, but I don't seem to have exactly that view. For example, when using the performance profiler, I can't actually pause the App.

    I did manage to track down the revision caused this problem (I create multiple instances of this class, and give them all a serial number and log their destruction). The scary thing is that the only change was that I made my app target the anniversary edition of Windows 10. Once I found that, I managed to confirm that by simply switching the target between 14393 and 10586, I can make the problem come and go. Which means that I have no idea what actual aspect of my code is causing this to happen.

    I will continue to pursue some of the diagnostics tools suggested in the blog post you linked, and see if I can find exactly what they're using and where it comes from. Do you happen to know if this is something that requires a specific version of VS2015, or if it should be present in any decently modern version? I also tried to use VS2017 to try to run the diagnostic tools, but couldn't find that particular view there either.

    Thanks,
    Tomas Hofmann

    Friday, March 17, 2017 11:03 PM