From 1a6733e86d0c1eb772c6f5eec4542435373bc42f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 18:06:23 +0800 Subject: [PATCH 1/6] Improve background wallpaper fetch --- .../Helper/WallpaperPathRetrieval.cs | 42 +++++++++++++++++-- .../Resources/Pages/WelcomePage2.xaml.cs | 21 +--------- .../ViewModels/SettingsPaneThemeViewModel.cs | 21 +--------- 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 8a42d480f..f79fea288 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -1,9 +1,10 @@ using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Windows.Documents; using System.Windows.Media; +using System.Windows.Media.Imaging; using Microsoft.Win32; using Windows.Win32; using Windows.Win32.UI.WindowsAndMessaging; @@ -14,7 +15,40 @@ public static class WallpaperPathRetrieval { private static readonly int MAX_PATH = 260; - public static unsafe string GetWallpaperPath() + private static readonly Dictionary wallpaperCache = new(); + + public static Brush GetWallpaperBrush() + { + var wallpaper = GetWallpaperPath(); + if (wallpaper is not null && File.Exists(wallpaper)) + { + // Since the wallpaper file name is the same (TranscodedWallpaper), + // we need to use the last modified date to differentiate them + var dateModified = File.GetLastWriteTime(wallpaper); + wallpaperCache.TryGetValue(dateModified, out var cachedWallpaper); + if (cachedWallpaper != null) + { + return new ImageBrush(cachedWallpaper) { Stretch = Stretch.UniformToFill }; + } + + // We should not dispose the memory stream since the bitmap is still in use + var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); + var bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.StreamSource = memStream; + bitmap.DecodePixelWidth = 800; + bitmap.DecodePixelHeight = 600; + bitmap.EndInit(); + bitmap.Freeze(); // Make the bitmap thread-safe + wallpaperCache[dateModified] = bitmap; + return new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; + } + + var wallpaperColor = GetWallpaperColor(); + return new SolidColorBrush(wallpaperColor); + } + + private static unsafe string GetWallpaperPath() { var wallpaperPtr = stackalloc char[MAX_PATH]; PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETDESKWALLPAPER, (uint)MAX_PATH, @@ -25,7 +59,7 @@ public static class WallpaperPathRetrieval return wallpaper.ToString(); } - public static Color GetWallpaperColor() + private static Color GetWallpaperColor() { RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", true); var result = key?.GetValue("Background", null); diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs index 004e4d6d2..1ed5747cd 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs @@ -5,8 +5,6 @@ using System; using System.Windows.Navigation; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.ViewModel; -using System.IO; -using System.Windows.Media.Imaging; using System.Windows.Media; namespace Flow.Launcher.Resources.Pages @@ -33,24 +31,7 @@ namespace Flow.Launcher.Resources.Pages public Brush PreviewBackground { - get - { - var wallpaper = WallpaperPathRetrieval.GetWallpaperPath(); - if (wallpaper is not null && File.Exists(wallpaper)) - { - var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); - var bitmap = new BitmapImage(); - bitmap.BeginInit(); - bitmap.StreamSource = memStream; - bitmap.DecodePixelWidth = 800; - bitmap.DecodePixelHeight = 600; - bitmap.EndInit(); - return new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; - } - - var wallpaperColor = WallpaperPathRetrieval.GetWallpaperColor(); - return new SolidColorBrush(wallpaperColor); - } + get => WallpaperPathRetrieval.GetWallpaperBrush(); } } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 980b2a811..ed933678d 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Windows.Media; -using System.Windows.Media.Imaging; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; @@ -14,7 +13,6 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using ModernWpf; -using Flow.Launcher.Core; using ThemeManager = Flow.Launcher.Core.Resource.ThemeManager; using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager; @@ -212,24 +210,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel public Brush PreviewBackground { - get - { - var wallpaper = WallpaperPathRetrieval.GetWallpaperPath(); - if (wallpaper is not null && File.Exists(wallpaper)) - { - var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); - var bitmap = new BitmapImage(); - bitmap.BeginInit(); - bitmap.StreamSource = memStream; - bitmap.DecodePixelWidth = 800; - bitmap.DecodePixelHeight = 600; - bitmap.EndInit(); - return new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; - } - - var wallpaperColor = WallpaperPathRetrieval.GetWallpaperColor(); - return new SolidColorBrush(wallpaperColor); - } + get => WallpaperPathRetrieval.GetWallpaperBrush(); } public ResultsViewModel PreviewResults From ff45f5f7f5215dc30de11333ff6c42b1aeb7b554 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 18:14:42 +0800 Subject: [PATCH 2/6] Cache image brush & Invoke on UI thread --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index f79fea288..7c74552be 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Win32; @@ -15,10 +16,16 @@ public static class WallpaperPathRetrieval { private static readonly int MAX_PATH = 260; - private static readonly Dictionary wallpaperCache = new(); + private static readonly Dictionary wallpaperCache = new(); public static Brush GetWallpaperBrush() { + // Invoke the method on the UI thread + if (!Application.Current.Dispatcher.CheckAccess()) + { + return Application.Current.Dispatcher.Invoke(GetWallpaperBrush); + } + var wallpaper = GetWallpaperPath(); if (wallpaper is not null && File.Exists(wallpaper)) { @@ -28,7 +35,7 @@ public static class WallpaperPathRetrieval wallpaperCache.TryGetValue(dateModified, out var cachedWallpaper); if (cachedWallpaper != null) { - return new ImageBrush(cachedWallpaper) { Stretch = Stretch.UniformToFill }; + return cachedWallpaper; } // We should not dispose the memory stream since the bitmap is still in use @@ -40,8 +47,10 @@ public static class WallpaperPathRetrieval bitmap.DecodePixelHeight = 600; bitmap.EndInit(); bitmap.Freeze(); // Make the bitmap thread-safe - wallpaperCache[dateModified] = bitmap; - return new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; + var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; + wallpaperBrush.Freeze(); // Make the brush thread-safe + wallpaperCache.Add(dateModified, wallpaperBrush); + return wallpaperBrush; } var wallpaperColor = GetWallpaperColor(); From 0fddb84735638940a9f3041a38800fd3e6de2c15 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 19:41:41 +0800 Subject: [PATCH 3/6] Add wallpaper path in cache dictionary --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 7c74552be..9f66a270c 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -16,7 +16,7 @@ public static class WallpaperPathRetrieval { private static readonly int MAX_PATH = 260; - private static readonly Dictionary wallpaperCache = new(); + private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new(); public static Brush GetWallpaperBrush() { @@ -26,20 +26,20 @@ public static class WallpaperPathRetrieval return Application.Current.Dispatcher.Invoke(GetWallpaperBrush); } - var wallpaper = GetWallpaperPath(); - if (wallpaper is not null && File.Exists(wallpaper)) + var wallpaperPath = GetWallpaperPath(); + if (wallpaperPath is not null && File.Exists(wallpaperPath)) { - // Since the wallpaper file name is the same (TranscodedWallpaper), - // we need to use the last modified date to differentiate them - var dateModified = File.GetLastWriteTime(wallpaper); - wallpaperCache.TryGetValue(dateModified, out var cachedWallpaper); + // Since the wallpaper file name can be the same (TranscodedWallpaper), + // we need to add the last modified date to differentiate them + var dateModified = File.GetLastWriteTime(wallpaperPath); + wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper); if (cachedWallpaper != null) { return cachedWallpaper; } // We should not dispose the memory stream since the bitmap is still in use - var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); + var memStream = new MemoryStream(File.ReadAllBytes(wallpaperPath)); var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = memStream; @@ -49,7 +49,7 @@ public static class WallpaperPathRetrieval bitmap.Freeze(); // Make the bitmap thread-safe var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; wallpaperBrush.Freeze(); // Make the brush thread-safe - wallpaperCache.Add(dateModified, wallpaperBrush); + wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); return wallpaperBrush; } From 9dbc174994e77124c2b42b2864ab6ab1f4d8ab10 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Feb 2025 15:34:59 +0800 Subject: [PATCH 4/6] Add cache size management & Add error handling --- .../Helper/WallpaperPathRetrieval.cs | 69 ++++++++++++------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 9f66a270c..eedc78eca 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -17,6 +17,7 @@ public static class WallpaperPathRetrieval private static readonly int MAX_PATH = 260; private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new(); + private const int MaxCacheSize = 3; public static Brush GetWallpaperBrush() { @@ -26,35 +27,55 @@ public static class WallpaperPathRetrieval return Application.Current.Dispatcher.Invoke(GetWallpaperBrush); } - var wallpaperPath = GetWallpaperPath(); - if (wallpaperPath is not null && File.Exists(wallpaperPath)) + try { - // Since the wallpaper file name can be the same (TranscodedWallpaper), - // we need to add the last modified date to differentiate them - var dateModified = File.GetLastWriteTime(wallpaperPath); - wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper); - if (cachedWallpaper != null) + var wallpaperPath = GetWallpaperPath(); + if (wallpaperPath is not null && File.Exists(wallpaperPath)) { - return cachedWallpaper; + // Since the wallpaper file name can be the same (TranscodedWallpaper), + // we need to add the last modified date to differentiate them + var dateModified = File.GetLastWriteTime(wallpaperPath); + wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper); + if (cachedWallpaper != null) + { + return cachedWallpaper; + } + + // We should not dispose the memory stream since the bitmap is still in use + var memStream = new MemoryStream(File.ReadAllBytes(wallpaperPath)); + var bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.StreamSource = memStream; + bitmap.DecodePixelWidth = 800; + bitmap.DecodePixelHeight = 600; + bitmap.EndInit(); + bitmap.Freeze(); // Make the bitmap thread-safe + var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; + wallpaperBrush.Freeze(); // Make the brush thread-safe + + // Manage cache size + if (wallpaperCache.Count >= MaxCacheSize) + { + // Remove the oldest wallpaper from the cache + var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault(); + if (oldestCache != default) + { + wallpaperCache.Remove(oldestCache); + } + } + + wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); + return wallpaperBrush; } - // We should not dispose the memory stream since the bitmap is still in use - var memStream = new MemoryStream(File.ReadAllBytes(wallpaperPath)); - var bitmap = new BitmapImage(); - bitmap.BeginInit(); - bitmap.StreamSource = memStream; - bitmap.DecodePixelWidth = 800; - bitmap.DecodePixelHeight = 600; - bitmap.EndInit(); - bitmap.Freeze(); // Make the bitmap thread-safe - var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; - wallpaperBrush.Freeze(); // Make the brush thread-safe - wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush); - return wallpaperBrush; + var wallpaperColor = GetWallpaperColor(); + return new SolidColorBrush(wallpaperColor); + } + catch (Exception ex) + { + App.API.LogException(nameof(WallpaperPathRetrieval), "Error retrieving wallpaper", ex); + return new SolidColorBrush(Colors.Transparent); } - - var wallpaperColor = GetWallpaperColor(); - return new SolidColorBrush(wallpaperColor); } private static unsafe string GetWallpaperPath() From c06042f96bee6f65fe1b4b761643a2e2bd495978 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Feb 2025 17:03:53 +0800 Subject: [PATCH 5/6] Fix API instance create twice issue & Make PluginManager.API private --- Flow.Launcher.Core/Plugin/PluginManager.cs | 4 +++- Flow.Launcher/MainWindow.xaml.cs | 2 +- .../SettingPages/ViewModels/SettingsPaneAboutViewModel.cs | 5 ++--- .../SettingPages/Views/SettingsPanePluginStore.xaml.cs | 3 +-- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 6e7b5ec60..09711051e 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -29,7 +29,9 @@ namespace Flow.Launcher.Core.Plugin public static readonly HashSet GlobalPlugins = new(); public static readonly Dictionary NonGlobalPlugins = new(); - public static IPublicAPI API { get; private set; } = Ioc.Default.GetRequiredService(); + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); private static PluginsSettings Settings; private static List _metadatas; diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 41dc68fd9..3f1bae090 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -438,7 +438,7 @@ namespace Flow.Launcher if (_settings.FirstLaunch) { _settings.FirstLaunch = false; - PluginManager.API.SaveAppAllSettings(); + App.API.SaveAppAllSettings(); OpenWelcomeWindow(); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index cb434f399..ade650284 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using System.Windows; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; -using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; @@ -77,7 +76,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel [RelayCommand] private void OpenSettingsFolder() { - PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Settings)); + App.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Settings)); } [RelayCommand] @@ -85,7 +84,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel { string settingsFolderPath = Path.Combine(DataLocation.DataDirectory(), Constant.Settings); string parentFolderPath = Path.GetDirectoryName(settingsFolderPath); - PluginManager.API.OpenDirectory(parentFolderPath); + App.API.OpenDirectory(parentFolderPath); } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs index dfb4a7eaf..db4763319 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs @@ -3,7 +3,6 @@ using System.ComponentModel; using System.Windows.Data; using System.Windows.Input; using System.Windows.Navigation; -using Flow.Launcher.Core.Plugin; using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.ViewModel; @@ -49,7 +48,7 @@ public partial class SettingsPanePluginStore private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e) { - PluginManager.API.OpenUrl(e.Uri.AbsoluteUri); + App.API.OpenUrl(e.Uri.AbsoluteUri); e.Handled = true; } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 650a27610..6b0144a03 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -442,7 +442,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void SelectHelp() { - PluginManager.API.OpenUrl("https://www.flowlauncher.com/docs/#/usage-tips"); + App.API.OpenUrl("https://www.flowlauncher.com/docs/#/usage-tips"); } [RelayCommand] diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index bae9292bf..46f8e00a2 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -134,20 +134,20 @@ namespace Flow.Launcher.ViewModel { var directory = PluginPair.Metadata.PluginDirectory; if (!string.IsNullOrEmpty(directory)) - PluginManager.API.OpenDirectory(directory); + App.API.OpenDirectory(directory); } [RelayCommand] private void OpenSourceCodeLink() { - PluginManager.API.OpenUrl(PluginPair.Metadata.Website); + App.API.OpenUrl(PluginPair.Metadata.Website); } [RelayCommand] private void OpenDeletePluginWindow() { - PluginManager.API.ChangeQuery($"{PluginManagerActionKeyword} uninstall {PluginPair.Metadata.Name}".Trim(), true); - PluginManager.API.ShowMainWindow(); + App.API.ChangeQuery($"{PluginManagerActionKeyword} uninstall {PluginPair.Metadata.Name}".Trim(), true); + App.API.ShowMainWindow(); } public static bool IsActionKeywordRegistered(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); From d8c547f7ef3a640b613778713508a9b111c90ab6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Feb 2025 18:10:58 +0800 Subject: [PATCH 6/6] Improve code quality --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index eedc78eca..a3bd83a97 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -15,9 +15,9 @@ namespace Flow.Launcher.Helper; public static class WallpaperPathRetrieval { private static readonly int MAX_PATH = 260; + private static readonly int MAX_CACHE_SIZE = 3; private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new(); - private const int MaxCacheSize = 3; public static Brush GetWallpaperBrush() { @@ -54,7 +54,7 @@ public static class WallpaperPathRetrieval wallpaperBrush.Freeze(); // Make the brush thread-safe // Manage cache size - if (wallpaperCache.Count >= MaxCacheSize) + if (wallpaperCache.Count >= MAX_CACHE_SIZE) { // Remove the oldest wallpaper from the cache var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault();