3

Closed

Memory leaks in ParentChangedNotifier

description

I'm currently writing an application which has multiple Windows which can be dynamically created, destroyed and recreated by the user. I noticed that the first instance of a Window is kept in memory until the application is destroyed, meaning that I will
often have two instances of the same Window in memory at any one time.

After a bit of hunting I've tracked this down to ParentChangedNotifierHelper.cs in the WPF Localization Extension. In the GetValueOrRegisterParentNotifier<T> a reference to the first instance of the view is added in the following block...



parentNotifiers.Add(target, new ParentChangedNotifier((FrameworkElement)depObj, () =>
{
ParentChangedAction(target);
}));


This reference hangs around forever and so the first instance of the view is never unloaded from memory.

I've reproduced the issue in very simple application (code available if needed). The application simply creates an instance of a view containing a localized Label.

Am I doing something wrong? Is there any way I can work around this?

Any help would be much appreciated!

file attachments

Closed Oct 3 at 10:10 AM by SeriousM

comments

MrCircuit wrote Nov 5, 2012 at 12:54 AM

Fixed now in the GitHub code - needs also an update of the XAMLMarkupExtensions code.
A combined release will be sent out with v2.1.2

roadz wrote Nov 5, 2012 at 9:39 AM

This test application illustrates the bug. The "Load" button on the "Loader" form creates a new instance of a popup window, shows it modally and then releases the reference to it. The constructor and finalizer output a debug message when an instance is created or finalized. You will notice that instance 0 is never finalized.

I will try to build and test your fix later on today. Thanks for the quick response!

MrCircuit wrote Nov 5, 2012 at 10:47 AM

With the fix, my memory profiler says that the instances are removed and the finalizer output also appears with a certain delay (probably due to the GC cycles).

roadz wrote Nov 5, 2012 at 11:02 AM

The debug output on my test application is a little unclear, but my memory profiler is showing that the Window is unloaded from memory after it is closed. Thanks again for your help, it's very much appreciated.

MrCircuit wrote Nov 12, 2012 at 3:31 PM

fixed in v2.1.2

** Closed by MrCircuit 11/12/2012 7:31AM

roadz wrote Feb 7 at 10:16 PM

Issue has reappeared in release 2.2.0. Now all instances of the view are leaked (not just the first instance as before).

roadz wrote Feb 7 at 10:42 PM

Strangely, if I specify the default assembly and dictionary the memory leak goes away. I could go through my app and change it to always specify this but it's weird that not doing this would introduce a leak
    lex:ResxLocalizationProvider.DefaultAssembly="LocalizationTest"
    lex:ResxLocalizationProvider.DefaultDictionary="TestResource"

MrCircuit wrote Feb 9 at 11:41 PM

I can verify the situation that you described and it seems to be connected to another issue.
I'm on it.

MrCircuit wrote Feb 10 at 9:23 PM

Hi, can you please test if the latest version on GitHub will fix your problem?

MrCircuit wrote Feb 10 at 9:24 PM

For your convenience, I attached the extension DLL.

roadz wrote Feb 17 at 10:15 PM

Sorry for the delayed reply, I didn't get a notification.

I've tried the attached DLL an that seems to work as expected. Thanks very much.

MrCircuit wrote Feb 17 at 10:38 PM

Great - thanks for your check.
Then I'll mark this issue as resolved and finish the upcoming release soon.

olathunberg wrote Apr 28 at 2:01 PM

In a nested environment like below, the issue still exists as stated above.

Leak is introduced due to the full specification of the header text, but the key is not found if not specified. Default values are provided and working on the main group.

If needed I will try to build a small example.

The example is using DevExpress.
       <dxdo:LayoutGroup Caption="{lex:Loc CustomerGroup}" >
                    <dxdo:LayoutControlItem Caption="{lex:Loc CustomerContact}">
                        <dxg:LookUpEdit DisplayMember="DisplayName" 
                                        ItemsSource="{Binding CustomerContacts}" 
                                        PopupWidth="1000"
                                        AutoPopulateColumns="False"
                                        TextWrapping="Wrap"
                                        NullText="{lex:Loc NoReference}">
                            <dxg:LookUpEdit.PopupContentTemplate>
                                <ControlTemplate>
                                    <dxg:GridControl Name="PART_GridControl" AutoExpandAllGroups="True">
                                        <dxg:GridControl.Columns>
                                            <dxg:GridColumn FieldName="FullName" 
                                                            Header="{lex:Loc LocalizeTest:TestLoc:ContactName}"
                                                            Width="150"
                                                            SortIndex="0"/>