Click here to Skip to main content
15,881,852 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C#
I am working on a Large wpf applications, We opted for Shared Resource Dictionary because ResourceDictionaries are always instantiated, everytime they are found in an XAML we might end up having one resource dictionary multiple times in memory. Get benifitted from this and cut down from 800mb down to 50mb, which is a really huge , Unfortunately this leads to memory leak. I figured this happens to everything that is instantiated via XAML like converters, user controls etc are kept in memory. and when i remove the converter and user control, it works fine. How can i avoid the memory leak using the shared resource dictionary.Thank you
The memory leak xaml is commented out in code


What I have tried:

XML
<pre lang="XML">
<UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <utility:SharedResourceDictionary SharedSource="/Arinc.UI.Common;component/Styles/GlobalStylesResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <converters:GridLengthToDoubleConverter x:Key="gridLengthConverter"/>
        </ResourceDictionary>
    </UserControl.Resources>
	
	 <DataGrid>
	 <!-- Memory Leak xaml
		<DataGridTextColumn MinWidth="140" Header="STATE" Binding="{Binding IncidentStateText}" CellStyle="{StaticResource BlinkingCellStyle}">
			<DataGridTextColumn.ElementStyle>
				<Style TargetType="{x:Type TextBlock}">
					<Setter Property="Foreground" Value="{Binding IncidentStateTextColor, Converter={StaticResource ColorToBrushConverter}}"/>
					<Setter Property="VerticalAlignment" Value="Center"/>
				</Style>
			</DataGridTextColumn.ElementStyle>
		</DataGridTextColumn>
		
		<DataGridTemplateColumn MinWidth="200" Header="DATE/TIME" SortDirection="Descending" CellStyle="{StaticResource BlinkingCellStyle}" SortMemberPath="Time">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <commonControls:DateTimeDisplayControl Content="{Binding Time}" DisplayFormat="ShortDateLongTime" Foreground="{Binding TimeColor, Converter={StaticResource ColorToBrushConverter}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
		-->		
		
		<DataGridTextColumn Width="200" Header="DATE/TIME" Binding="{Binding Time, StringFormat='G'}" CellStyle="{StaticResource BlinkingCellStyle}" SortDirection="Descending" SortMemberPath="Time">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">						
                    <!--<Setter Property="Foreground" Value="{Binding TimeColor, Converter={StaticResource ColorToBrushConverter}}"/>-->
                    <Setter Property="VerticalAlignment" Value="Center"/>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
		
		 <DataGridTextColumn Width="200" Header="DATE/TIME" Binding="{Binding Time, StringFormat='G'}" CellStyle="{StaticResource BlinkingCellStyle}" SortDirection="Descending" SortMemberPath="Time">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">
                    <!--<Setter Property="Foreground" Value="{Binding TimeColor, Converter={StaticResource ColorToBrushConverter}}"/>-->
                    <Setter Property="VerticalAlignment" Value="Center"/>
                </Style>
            </DataGridTextColumn.ElementStyle>
		</DataGridTextColumn>
				
	  </DataGrid>
</pre>


C#
/// <summary>
/// Loads singleton instance of ResourceDictionary to current scope;
/// </summary>
public class SharedResourceDictionary : ResourceDictionary
{
  /// <summary>
  /// store weak references to loaded ResourceDictionary, to ensure that ResourceDictionary won't be instanciated multiple times
  /// </summary>
  protected static Dictionary<string, WeakReference> SharedResources = new Dictionary<string, WeakReference>();

  public string SharedSource
  {
    get { return _SharedSource; }
    set
    {
      if (_SharedSource != value)
      {
        _SharedSource = value;
        sharedSourceChanged();
      }
    }
  }
  private string _SharedSource;


  private void sharedSourceChanged()
  {
    //ResourceDictionary will be instanciated only once
    ResourceDictionary sharedResourceDictionary;

    lock (SharedResources)
    {
      WeakReference weakResourceDictionary = null;
      if (SharedResources.ContainsKey(_SharedSource))
      {
        weakResourceDictionary = SharedResources[_SharedSource];
      }
      else
      {
        SharedResources.Add(_SharedSource, null);
      }

      if (weakResourceDictionary == null || !weakResourceDictionary.IsAlive) //load ResourceDictionary or get reference to exiting
      {
        sharedResourceDictionary = (ResourceDictionary)Application.LoadComponent(new Uri(_SharedSource, UriKind.Relative));
        weakResourceDictionary = new WeakReference(sharedResourceDictionary);
      }
      else
      {
        sharedResourceDictionary = (ResourceDictionary)weakResourceDictionary.Target;
      }

      SharedResources[_SharedSource] = weakResourceDictionary;
    }


    if (Application.Current != null)
    {
      //if sharedResourceDictionary is defined in application scope do not add it to again to current scope
      if (containsResourceDictionary(Application.Current.Resources, sharedResourceDictionary))
      {
        return;
      }
    }

    this.MergedDictionaries.Add(sharedResourceDictionary);
  }

  private bool containsResourceDictionary(ResourceDictionary scope, ResourceDictionary rs)
  {
    foreach (var subScope in scope.MergedDictionaries)
    {
      if (subScope == rs) return true;
      if (containsResourceDictionary(subScope, rs)) return true;
    }
    return false;
  }
}
Posted
Updated 14-Nov-16 9:26am
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900