Improve sub menu loading performance

Use thread pool for background icon loading.
This eliminates massive thread spawns on very large folders.
This commit is contained in:
Peter Kirmeier 2023-09-23 12:18:01 +02:00
parent dcae66979f
commit 5e2d17b02b

View file

@ -23,9 +23,32 @@ namespace SystemTrayMenu.Utilities
/// </summary> /// </summary>
internal static class IconReader internal static class IconReader
{ {
private static readonly BitmapSource? OverlayImage = (BitmapSource?)Application.Current.Resources["LinkArrowIconImage"];
private static readonly ConcurrentDictionary<string, BitmapSource> IconDictPersistent = new(); private static readonly ConcurrentDictionary<string, BitmapSource> IconDictPersistent = new();
private static readonly ConcurrentDictionary<string, BitmapSource> IconDictCache = new(); private static readonly ConcurrentDictionary<string, BitmapSource> IconDictCache = new();
private static readonly BitmapSource? OverlayImage = (BitmapSource?)Application.Current.Resources["LinkArrowIconImage"]; private static readonly BlockingCollection<Action> IconFactoryQueue = new();
private static readonly List<Thread> IconFactoryThreadPoolSTA = new(16);
static IconReader()
{
for (int i = 0; i < IconFactoryThreadPoolSTA.Capacity; i++)
{
Thread thread = new(IconFactoryWorkerSTA);
thread.Name = "IconFactory STA #" + i.ToString();
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
IconFactoryThreadPoolSTA.Add(thread);
}
void IconFactoryWorkerSTA()
{
while(true)
{
IconFactoryQueue.Take()();
}
}
}
internal static void ClearCacheWhenLimitReached() internal static void ClearCacheWhenLimitReached()
{ {
@ -110,14 +133,11 @@ namespace SystemTrayMenu.Utilities
} }
else else
{ {
Thread thread = new(UpdateIconInBackgroundSTA); IconFactoryQueue.Add(() =>
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
void UpdateIconInBackgroundSTA()
{ {
BitmapSource icon = DictIconCache(checkPersistentFirst).GetOrAdd(key, factory); BitmapSource icon = DictIconCache(checkPersistentFirst).GetOrAdd(key, factory);
onIconLoaded(icon); onIconLoaded(icon);
} });
return false; return false;
} }