Memory leak when using SharedResourceDictionary

前端 未结 2 1285
无人及你
无人及你 2020-12-24 09:18

if you worked on some larger wpf applications you might be familiar with this. Because ResourceDictionaries are always instantiated, everytime they are found in an XAML we m

相关标签:
2条回答
  • 2020-12-24 09:42

    I am not quite sure if this will solve your issue. But I had similar issues with ResourceDictionary referencing controls and its to do with lazy hydration. Here is a post on it. And this code resolved my issues:

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            WalkDictionary(this.Resources);
    
            base.OnStartup(e);
        }
    
        private static void WalkDictionary(ResourceDictionary resources)
        {
            foreach (DictionaryEntry entry in resources)
            {
            }
    
            foreach (ResourceDictionary rd in resources.MergedDictionaries)
                WalkDictionary(rd);
        }
    }
    
    0 讨论(0)
  • 2020-12-24 09:45

    I'm running into the same issue of needing shared resource directories in a large-ish WPF project. Reading the source article and the comments, I incorporated a couple fixes to the SharedDirectory class as suggested in the comments, which seem to have removed the strong reference (stored in _sourceUri) and also make the designer work correctly. I tested your example and it works, both in the designer and MemProfiler successfully noting no held references. I'd love to know if anyone has improved it further, but this is what i'm going with for now:

    public class SharedResourceDictionary : ResourceDictionary
    {
        /// <summary>
        /// Internal cache of loaded dictionaries 
        /// </summary>
        public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =
            new Dictionary<Uri, ResourceDictionary>();
    
        /// <summary>
        /// Local member of the source uri
        /// </summary>
        private Uri _sourceUri;
    
        /// <summary>
        /// Gets or sets the uniform resource identifier (URI) to load resources from.
        /// </summary>
        public new Uri Source
        {
            get {
                if (IsInDesignMode)
                    return base.Source;
                return _sourceUri;
            }
            set
            {
                if (IsInDesignMode)
                {
                    try
                    {
                        _sourceUri = new Uri(value.OriginalString);
                    }
                    catch
                    {
                        // do nothing?
                    }
    
                    return;
                }
    
                try
                {
                    _sourceUri = new Uri(value.OriginalString);
                }
                catch
                {
                    // do nothing?
                }
    
                if (!_sharedDictionaries.ContainsKey(value))
                {
                    // If the dictionary is not yet loaded, load it by setting
                    // the source of the base class
    
                    base.Source = value;
    
                    // add it to the cache
                    _sharedDictionaries.Add(value, this);
                }
                else
                {
                    // If the dictionary is already loaded, get it from the cache
                    MergedDictionaries.Add(_sharedDictionaries[value]);
                }
            }
        }
    
        private static bool IsInDesignMode
        {
            get
            {
                return (bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
                typeof(DependencyObject)).Metadata.DefaultValue;
            }
        } 
    }
    
    0 讨论(0)
提交回复
热议问题