using System.Collections.Concurrent; using System.IO; using System.Windows; using System.Windows.Media; namespace DeskCore; /// Lädt Icons auf einem eigenen STA-Thread (Shell-COM braucht STA) und cached sie. public static class IconLoader { private static readonly ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase); private static readonly BlockingCollection<(IconItem Item, int Size)> _queue = new(); static IconLoader() { var t = new Thread(Work) { IsBackground = true, Name = "IconLoader" }; t.SetApartmentState(ApartmentState.STA); t.Start(); } private static string Key(string path, int size) { DateTime stamp; try { stamp = File.GetLastWriteTimeUtc(path); } catch { stamp = default; } return $"{size}|{stamp.Ticks}|{path}"; } /// Setzt das Icon sofort aus dem Cache oder lädt es im Hintergrund nach. public static void Load(IconItem item, int size) { if (_cache.TryGetValue(Key(item.Path, size), out var icon)) item.Icon = icon; else _queue.Add((item, size)); } private static void Work() { foreach (var (item, size) in _queue.GetConsumingEnumerable()) { var key = Key(item.Path, size); if (!_cache.TryGetValue(key, out var icon)) { icon = ShellIcon.Get(item.Path, size); _cache[key] = icon; } var result = icon; Application.Current?.Dispatcher.BeginInvoke(() => item.Icon = result); } } }