diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj
index 02cd8f869b..3b5155f9fd 100644
--- a/Wox.Core/Wox.Core.csproj
+++ b/Wox.Core/Wox.Core.csproj
@@ -84,7 +84,7 @@
-
+
diff --git a/Wox/App.xaml.cs b/Wox/App.xaml.cs
index d76f0d4fcc..7aded30ce1 100644
--- a/Wox/App.xaml.cs
+++ b/Wox/App.xaml.cs
@@ -23,7 +23,7 @@ namespace Wox
{
private const string Unique = "Wox_Unique_Application_Mutex";
public static MainWindow Window { get; private set; }
-
+ public static ImageLoader.ImageLoader ImageLoader;
public static PublicAPIInstance API { get; private set; }
[STAThread]
@@ -48,7 +48,9 @@ namespace Wox
ThreadPool.SetMaxThreads(30, 10);
ThreadPool.SetMinThreads(10, 5);
- ThreadPool.QueueUserWorkItem(_ => { ImageLoader.ImageLoader.PreloadImages(); });
+
+ ImageLoader = new ImageLoader.ImageLoader();
+ ThreadPool.QueueUserWorkItem(_ => { ImageLoader.PreloadImages(); });
PluginManager.Initialize();
diff --git a/Wox/Converters/ImagePathConverter.cs b/Wox/Converters/ImagePathConverter.cs
index eb92e62514..4a5beb5b25 100644
--- a/Wox/Converters/ImagePathConverter.cs
+++ b/Wox/Converters/ImagePathConverter.cs
@@ -13,8 +13,7 @@ namespace Wox.Converters
{
return null;
}
-
- return ImageLoader.ImageLoader.Load(value.ToString());
+ return App.ImageLoader.Load(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Wox/ImageLoader/ImageCache.cs b/Wox/ImageLoader/ImageCache.cs
index e317c70c9a..8c6ab12fa8 100644
--- a/Wox/ImageLoader/ImageCache.cs
+++ b/Wox/ImageLoader/ImageCache.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Wox.Infrastructure.Storage;
@@ -8,39 +9,26 @@ namespace Wox.ImageLoader
[Serializable]
public class ImageCache
{
- private int counter;
- private const int maxCached = 200;
- public Dictionary TopUsedImages = new Dictionary();
+ private const int MaxCached = 200;
+ public ConcurrentDictionary TopUsedImages = new ConcurrentDictionary();
public void Add(string path)
{
if (TopUsedImages.ContainsKey(path))
{
- TopUsedImages[path] = TopUsedImages[path] + 1 ;
+ TopUsedImages[path] = TopUsedImages[path] + 1;
}
else
{
- TopUsedImages.Add(path, 1);
+ TopUsedImages[path] = 1;
}
- if (TopUsedImages.Count > maxCached)
+ if (TopUsedImages.Count > MaxCached)
{
- TopUsedImages = TopUsedImages.OrderByDescending(o => o.Value)
- .Take(maxCached)
- .ToDictionary(i => i.Key, i => i.Value);
- }
-
- if (++counter == 30)
- {
- counter = 0;
- }
- }
-
- public void Remove(string path)
- {
- if (TopUsedImages.ContainsKey(path))
- {
- TopUsedImages.Remove(path);
+ var images = TopUsedImages.OrderByDescending(o => o.Value)
+ .Take(MaxCached)
+ .ToDictionary(i => i.Key, i => i.Value);
+ TopUsedImages = new ConcurrentDictionary(images);
}
}
}
diff --git a/Wox/ImageLoader/ImageLoader.cs b/Wox/ImageLoader/ImageLoader.cs
index 17e7974dea..fe655b4c82 100644
--- a/Wox/ImageLoader/ImageLoader.cs
+++ b/Wox/ImageLoader/ImageLoader.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
@@ -7,6 +8,7 @@ using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using System.Linq;
using Wox.Infrastructure;
using Wox.Infrastructure.Storage;
@@ -14,9 +16,9 @@ namespace Wox.ImageLoader
{
public class ImageLoader
{
- private static readonly Dictionary ImageSources = new Dictionary();
+ private readonly ConcurrentDictionary ImageSources = new ConcurrentDictionary();
- private static readonly List imageExts = new List
+ private readonly List ImageExts = new List
{
".png",
".jpg",
@@ -27,7 +29,7 @@ namespace Wox.ImageLoader
".ico"
};
- private static readonly List selfExts = new List
+ private readonly List SelfExts = new List
{
".exe",
".lnk",
@@ -37,10 +39,10 @@ namespace Wox.ImageLoader
".appref-ms"
};
- private static readonly ImageCache _cache;
- private static readonly BinaryStorage _storage;
+ private readonly ImageCache _cache;
+ private readonly BinaryStorage _storage;
- static ImageLoader()
+ public ImageLoader()
{
_storage = new BinaryStorage();
_cache = _storage.Load();
@@ -51,7 +53,7 @@ namespace Wox.ImageLoader
_storage.Save();
}
- private static ImageSource GetIcon(string fileName)
+ private ImageSource GetIcon(string fileName)
{
try
{
@@ -68,32 +70,28 @@ namespace Wox.ImageLoader
return null;
}
- public static void PreloadImages()
+ public void PreloadImages()
{
- //ImageCacheStroage.Instance.TopUsedImages can be changed during foreach, so we need to make a copy
- var imageList = new Dictionary(_cache.TopUsedImages);
- Stopwatch.Debug($"Preload {imageList.Count} images", () =>
+ Stopwatch.Debug($"Preload {_cache.TopUsedImages.Count} images", () =>
{
- foreach (var image in imageList)
- {
- if (!ImageSources.ContainsKey(image.Key))
- {
- ImageSource img = Load(image.Key, false);
- if (img != null)
- {
- img.Freeze(); //to make it copy to UI thread
- if (!ImageSources.ContainsKey(image.Key))
- {
- KeyValuePair copyedImg = image;
- ImageSources.Add(copyedImg.Key, img);
- }
- }
- }
- }
+ _cache.TopUsedImages.AsParallel().Where(i => !ImageSources.ContainsKey(i.Key)).ForAll(i =>
+ {
+ var img = Load(i.Key, false);
+ if (img != null)
+ {
+ // todo happlebao magic
+ // the image created on other threads can be accessed from main ui thread,
+ // this line made it possible
+ // should be changed the Dispatcher.InvokeAsync in the future
+ img.Freeze();
+
+ ImageSources[i.Key] = img;
+ }
+ });
});
}
- public static ImageSource Load(string path, bool addToCache = true)
+ public ImageSource Load(string path, bool addToCache = true)
{
if (string.IsNullOrEmpty(path)) return null;
ImageSource img = null;
@@ -118,21 +116,20 @@ namespace Wox.ImageLoader
{
img = new BitmapImage(new Uri(path));
}
- else if (selfExts.Contains(ext) && File.Exists(path))
+ else if (SelfExts.Contains(ext) && File.Exists(path))
{
img = GetIcon(path);
}
- else if (!string.IsNullOrEmpty(path) && imageExts.Contains(ext) && File.Exists(path))
+ else if (!string.IsNullOrEmpty(path) && ImageExts.Contains(ext) && File.Exists(path))
{
img = new BitmapImage(new Uri(path));
}
-
if (img != null && addToCache)
{
if (!ImageSources.ContainsKey(path))
{
- ImageSources.Add(path, img);
+ ImageSources[path] = img;
}
}
}
@@ -141,7 +138,7 @@ namespace Wox.ImageLoader
}
// http://blogs.msdn.com/b/oldnewthing/archive/2011/01/27/10120844.aspx
- private static Icon GetFileIcon(string name)
+ private Icon GetFileIcon(string name)
{
SHFILEINFO shfi = new SHFILEINFO();
uint flags = SHGFI_SYSICONINDEX;
diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs
index 151a8d338b..adc626a9df 100644
--- a/Wox/SettingWindow.xaml.cs
+++ b/Wox/SettingWindow.xaml.cs
@@ -550,7 +550,7 @@ namespace Wox
pluginAuthor.Text = InternationalizationManager.Instance.GetTranslation("author") + ": " + pair.Metadata.Author;
pluginSubTitle.Text = pair.Metadata.Description;
pluginId = pair.Metadata.ID;
- pluginIcon.Source = ImageLoader.ImageLoader.Load(pair.Metadata.FullIcoPath);
+ pluginIcon.Source = App.ImageLoader.Load(pair.Metadata.FullIcoPath);
var customizedPluginConfig = _settings.PluginSettings[pluginId];
cbDisablePlugin.IsChecked = customizedPluginConfig != null && customizedPluginConfig.Disabled;
diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj
index 3a96cbe4fa..941f5017a9 100644
--- a/Wox/Wox.csproj
+++ b/Wox/Wox.csproj
@@ -125,7 +125,7 @@
-
+