diff --git a/Plugins/Wox.Plugin.Program/Main.cs b/Plugins/Wox.Plugin.Program/Main.cs index 876f571bc8..86431be80a 100644 --- a/Plugins/Wox.Plugin.Program/Main.cs +++ b/Plugins/Wox.Plugin.Program/Main.cs @@ -16,13 +16,13 @@ namespace Wox.Plugin.Program public class Main : ISettingProvider, IPlugin, IPluginI18n, IContextMenu, ISavable { private static readonly object IndexLock = new object(); - private static Win32[] _win32s = { }; - private static UWP.Application[] _uwps = { }; + private static Win32[] _win32s; + private static UWP.Application[] _uwps; private static PluginInitContext _context; - private static ProgramIndexCache _cache; - private static BinaryStorage _cacheStorage; + private static BinaryStorage _win32Storage; + private static BinaryStorage _uwpStorage; private static Settings _settings; private readonly PluginJsonStorage _settingsStorage; @@ -33,13 +33,10 @@ namespace Wox.Plugin.Program Stopwatch.Normal("Preload programs", () => { - _cacheStorage = new BinaryStorage(); - _cache = _cacheStorage.Load(); - - var w = _cache.Win32s; - _win32s = w ?? new Win32[] {}; - var u = _cache.UWPs; - _uwps = u ?? new UWP.Application[] { }; + _win32Storage = new BinaryStorage("Win32Cache"); + _win32s = _win32Storage.TryLoad(new Win32[] { }); + _uwpStorage = new BinaryStorage("UWPCache"); + _uwps = _uwpStorage.TryLoad(new UWP.Application[] { }); }); Log.Info($"Preload {_win32s.Length} win32 programs from cache"); @@ -53,9 +50,8 @@ namespace Wox.Plugin.Program public void Save() { _settingsStorage.Save(); - _cache.Win32s = _win32s; - _cache.UWPs = _uwps; - _cacheStorage.Save(); + _win32Storage.Save(_win32s); + _uwpStorage.Save(_uwps); } public List Query(Query query) @@ -76,8 +72,8 @@ namespace Wox.Plugin.Program public static void IndexPrograms() { - Win32[] w = {} ; - UWP.Application[] u = {}; + Win32[] w = { }; + UWP.Application[] u = { }; var t1 = Task.Run(() => { w = Win32.All(_settings); diff --git a/Plugins/Wox.Plugin.Program/ProgramIndexCache.cs b/Plugins/Wox.Plugin.Program/ProgramIndexCache.cs deleted file mode 100644 index b1c7783c2d..0000000000 --- a/Plugins/Wox.Plugin.Program/ProgramIndexCache.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using Wox.Plugin.Program.Programs; - -namespace Wox.Plugin.Program -{ - [Serializable] - public class ProgramIndexCache - { - public Win32[] Win32s = { }; - public UWP.Application[] UWPs = { }; - } -} \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj index 690940b247..e6ba6f5c50 100644 --- a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj +++ b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj @@ -76,7 +76,6 @@ - ProgramSetting.xaml diff --git a/Wox.Infrastructure/Image/ImageCache.cs b/Wox.Infrastructure/Image/ImageCache.cs index c5888a82ce..a0fac88cca 100644 --- a/Wox.Infrastructure/Image/ImageCache.cs +++ b/Wox.Infrastructure/Image/ImageCache.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; +using System.Windows.Media; namespace Wox.Infrastructure.Image { @@ -8,29 +10,35 @@ namespace Wox.Infrastructure.Image public class ImageCache { private const int MaxCached = 200; - public ConcurrentDictionary TopUsedImages = new ConcurrentDictionary(); + public ConcurrentDictionary Usage = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _data = new ConcurrentDictionary(); - public void Add(string path) + + public ImageSource this[string path] { - if (TopUsedImages.ContainsKey(path)) + get { - TopUsedImages[path] = TopUsedImages[path] + 1; - } - else - { - TopUsedImages[path] = 1; + Usage.AddOrUpdate(path, 1, (k, v) => v + 1); + var i = _data[path]; + return i; } + set { _data[path] = value; } } public void Cleanup() { - if (TopUsedImages.Count > MaxCached) - { - var images = TopUsedImages.OrderByDescending(o => o.Value) - .Take(MaxCached) - .ToDictionary(i => i.Key, i => i.Value); - TopUsedImages = new ConcurrentDictionary(images); - } + var images = Usage + .OrderByDescending(o => o.Value) + .Take(MaxCached) + .ToDictionary(i => i.Key, i => i.Value); + Usage = new ConcurrentDictionary(images); + } + + public bool ContainsKey(string key) + { + var contains = _data.ContainsKey(key); + return contains; } } + } diff --git a/Wox.Infrastructure/Image/ImageLoader.cs b/Wox.Infrastructure/Image/ImageLoader.cs index 2a827acdd1..aa74769b16 100644 --- a/Wox.Infrastructure/Image/ImageLoader.cs +++ b/Wox.Infrastructure/Image/ImageLoader.cs @@ -15,7 +15,8 @@ namespace Wox.Infrastructure.Image { public static class ImageLoader { - private static readonly ConcurrentDictionary ImageSources = new ConcurrentDictionary(); + private static readonly ImageCache ImageCache = new ImageCache(); + private static readonly BinaryStorage> Storage; private static readonly string[] ImageExtions = @@ -29,19 +30,17 @@ namespace Wox.Infrastructure.Image ".ico" }; - private static readonly ImageCache _cache; - private static readonly BinaryStorage _storage; static ImageLoader() { - _storage = new BinaryStorage(); - _cache = _storage.Load(); + Storage = new BinaryStorage> ("ImageCache"); + ImageCache.Usage = Storage.TryLoad(new ConcurrentDictionary()); } public static void Save() { - _cache.Cleanup(); - _storage.Save(); + ImageCache.Cleanup(); + Storage.Save(ImageCache.Usage); } private static ImageSource ShellIcon(string fileName) @@ -78,7 +77,7 @@ namespace Wox.Infrastructure.Image catch (System.Exception e) { Log.Exception(e); - return ImageSources[Constant.ErrorIcon]; + return ImageCache[Constant.ErrorIcon]; } } @@ -88,22 +87,22 @@ namespace Wox.Infrastructure.Image { ImageSource img = new BitmapImage(new Uri(icon)); img.Freeze(); - ImageSources[icon] = img; + ImageCache[icon] = img; } Task.Run(() => { Stopwatch.Normal("Preload images from cache", () => { - _cache.TopUsedImages.AsParallel().Where(i => !ImageSources.ContainsKey(i.Key)).ForAll(i => + ImageCache.Usage.AsParallel().Where(i => !ImageCache.ContainsKey(i.Key)).ForAll(i => { var img = Load(i.Key); if (img != null) { - ImageSources[i.Key] = img; + ImageCache[i.Key] = img; } }); }); - Log.Info($"Preload {_cache.TopUsedImages.Count} images from cache"); + Log.Info($"Preload {ImageCache.Usage.Count} images from cache"); }); } @@ -112,13 +111,11 @@ namespace Wox.Infrastructure.Image ImageSource image; if (string.IsNullOrEmpty(path)) { - image = ImageSources[Constant.ErrorIcon]; - _cache.Add(Constant.ErrorIcon); + image = ImageCache[Constant.ErrorIcon]; } - else if (ImageSources.ContainsKey(path)) + else if (ImageCache.ContainsKey(path)) { - image = ImageSources[path]; - _cache.Add(path); + image = ImageCache[path]; } else { @@ -146,7 +143,7 @@ namespace Wox.Infrastructure.Image } else { - image = ImageSources[Constant.ErrorIcon]; + image = ImageCache[Constant.ErrorIcon]; path = Constant.ErrorIcon; } } @@ -159,12 +156,11 @@ namespace Wox.Infrastructure.Image } else { - image = ImageSources[Constant.ErrorIcon]; + image = ImageCache[Constant.ErrorIcon]; path = Constant.ErrorIcon; } } - ImageSources[path] = image; - _cache.Add(path); + ImageCache[path] = image; image.Freeze(); } return image; diff --git a/Wox.Infrastructure/Storage/BinaryStorage.cs b/Wox.Infrastructure/Storage/BinaryStorage.cs index f18df92c5b..cca3d7fe1d 100644 --- a/Wox.Infrastructure/Storage/BinaryStorage.cs +++ b/Wox.Infrastructure/Storage/BinaryStorage.cs @@ -13,19 +13,20 @@ namespace Wox.Infrastructure.Storage /// Normally, it has better performance, but not readable /// You MUST mark implement class as Serializable /// - public class BinaryStorage : Storage where T : new() + public class BinaryStorage : Storage { - public BinaryStorage() + public BinaryStorage(string filename) { - FileSuffix = ".dat"; + FileSuffix = ".cache"; DirectoryName = "Cache"; DirectoryPath = Path.Combine(DirectoryPath, DirectoryName); + FileName = filename; FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix); ValidateDirectory(); } - public override T Load() + public T TryLoad(T defaultData) { if (File.Exists(FilePath)) { @@ -33,23 +34,25 @@ namespace Wox.Infrastructure.Storage { if (stream.Length > 0) { - Deserialize(stream); + var d = Deserialize(stream, defaultData); + return d; } else { stream.Close(); - LoadDefault(); + Save(defaultData); + return defaultData; } } } else { - LoadDefault(); + Save(defaultData); + return defaultData; } - return Data; } - private void Deserialize(FileStream stream) + private T Deserialize(FileStream stream, T defaultData) { //http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; @@ -60,14 +63,15 @@ namespace Wox.Infrastructure.Storage try { - Data = (T) binaryFormatter.Deserialize(stream); + var t = (T) binaryFormatter.Deserialize(stream); + return t; } catch (System.Exception e) { Log.Error($"Broken cache file: {FilePath}"); Log.Exception(e); stream.Close(); - LoadDefault(); + return defaultData; } finally { @@ -75,12 +79,6 @@ namespace Wox.Infrastructure.Storage } } - public override void LoadDefault() - { - Data = new T(); - Save(); - } - private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { Assembly ayResult = null; @@ -97,7 +95,7 @@ namespace Wox.Infrastructure.Storage return ayResult; } - public override void Save() + public void Save(T data) { using (var stream = new FileStream(FilePath, FileMode.Create)) { @@ -108,7 +106,7 @@ namespace Wox.Infrastructure.Storage try { - binaryFormatter.Serialize(stream, Data); + binaryFormatter.Serialize(stream, data); } catch (SerializationException e) { diff --git a/Wox.Infrastructure/Storage/Storage.cs b/Wox.Infrastructure/Storage/Storage.cs index 127f8b852f..0b8302d251 100644 --- a/Wox.Infrastructure/Storage/Storage.cs +++ b/Wox.Infrastructure/Storage/Storage.cs @@ -7,7 +7,7 @@ namespace Wox.Infrastructure.Storage { protected T Data; protected Type DataType { get; } - public string FileName { get; } + public string FileName { get; set; } public string FilePath { get; set; } public string FileSuffix { get; set; } public string DirectoryPath { get; set; }