locked
Custom Events in C++/CX runtime component (garbage collection).

    Question

  • Hi there,

    I've created a small Windows Runtime Component in C++/CX. I did some experiments to see at which point it would become eligible for garbage collection. This WRC (let's call it Component1) is derived from a ContentControl, and basically only displays a rectangle. So, in my App I have a MainPage which in turns contains a Component1. Also, MainPage has a button which navigates to a new instance of a MainPage, as well as a button which triggers garbage collection.

    When I navigate to a new page and click on the "Collect" button, I expect that my old MainPage will be reclaimed. I would also expect that the Component1 contained in that MainPage to be reclaimed. A quick test confirmed this was the case.

    However, I then added an event to Component1, and when MainPage subscribes to this event, neither will get reclaimed.

    I've attached a little bit of code to illustrate:

    public delegate void MyCustomEventHandler();
    
    	public ref class Component1 sealed : Windows::UI::Xaml::Controls::ContentControl
        {
        public:
            Component1();
    		
    	event MyCustomEventHandler^ MyCustomEvent;
    
            // ....
    
        }
    }

    MainPage then subscribes as follows:

    public MainPage()
    {
        this.InitializeComponent();
        _Component = new MyComponent.Component1();
    
        // Adding or removing this will influence whether or not this thing can be reclaimed by the garbage collector
        _Component.MyCustomEvent += _Component_MyCustomEvent;
    
        // ...
    }

    I've been looking around a bit on the web, but didn't find any "better" way to use events. Using DependencyProperties with PropertyChanged callbacks won't work on my control. Is there a way to register and raise these events so that subscribing to them does not cause Component1 to stay around. Is the reccommended solution to simply detach all the events when you know the page won't be needed anymore (e.g. OnNavigatedFrom) or something like that?

    Thanks in advance,

    Tomas

    Tuesday, August 13, 2013 6:14 PM

Answers

  • Correct. You need to remove the event handlers when you are done with them. This is often done when navigating away from the page. Otherwise the event maintains a reference which keeps the object alive

    It isn't central to you point, but C++/Cx doesn't use a garbage collector. It uses reference counting and deletes objects when the reference count falls to 0.

    --Rob

    • Marked as answer by T Hofmann Tuesday, August 13, 2013 7:17 PM
    Tuesday, August 13, 2013 6:44 PM
    Owner

All replies

  • Correct. You need to remove the event handlers when you are done with them. This is often done when navigating away from the page. Otherwise the event maintains a reference which keeps the object alive

    It isn't central to you point, but C++/Cx doesn't use a garbage collector. It uses reference counting and deletes objects when the reference count falls to 0.

    --Rob

    • Marked as answer by T Hofmann Tuesday, August 13, 2013 7:17 PM
    Tuesday, August 13, 2013 6:44 PM
    Owner
  • Rob, is this even true for event handlers declared in XAML?
    Tuesday, August 13, 2013 6:52 PM
  • Thanks Rob,

    I guess it can't be helped then. The reason this isn't ideal is that I'm not developing apps directly, but components for others to use. This will force me to tell customers that they have to "unsubscribe" a bunch of things. It's not the end of the world, but it would have been nicer if I could make my components do it automatically. In particular, I wanted to make sure that if I shipped it where explicit unsubscribing was necessary, at least it was the "right" thing :)

    As for C++/CX being reference counted, I knew that, but since my MainPage was in C#, I didn't know how it would work. That is, is my component something that can be garbage collected as a whole while it's internal workings are reference counted, or as soon as I created this component from C#, does it do it's own little reference counting?

    Also, what I noticed is that I could subscribed to my component's PointerPressed event, but not to my own custom events. I guess from your answer there is no way to create my own custom events in a way that makes them work like the pre-defined event in terms of reference counting?

    Thanks,

    Tomas

    Tuesday, August 13, 2013 7:12 PM
  • Sorry, I missed that you had C# as well as C++/Cx. The C++ code will be reference counted, but the reference won't drop until the .Net code holding it has been garbage collected.

    There is a bug in Windows 8 where some Xaml event references never go out of scope and so can't be released. This is fixed in Windows 8.1, but explicit references still need to be unhooked by the application. This is the same for built in events as it is for your component.

    Tuesday, August 13, 2013 7:58 PM
    Owner
  • Thanks again Rob,

    Another follow up question then. Let's say I have a class that attaches to some C+++/CX component and subscribes to some custom event as discussed.

    E.g.Component1 (C++/CX component).

    MainPage (C#).

    EventSwallower (C# class, it subscribes to a custom even in Component1).

    I guess at this point EventSwallower needs to somehow provide a way for MainPage to tell it to unsubscribe when it's no longer needed. Would this best be done using the IDisposable interface on EventSwallower and then having MainPage call _eventSwallower.Dispose()? Or should Dispose be used for something else and instead I should provide some form of EventSwallower.Unsubscribe() function?

    Thanks,

    Tomas

    Tuesday, August 13, 2013 9:57 PM