From 27ae5facbe5bd5383fbe104dd9369b4a7fd67a13 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Sun, 15 Aug 2021 13:39:06 -0600 Subject: [PATCH] Improved PictureStorage thread safety and more intuitive naming. --- FileManager/PictureStorage.cs | 61 ++++++++++--------- LibationWinForms/GridEntry.cs | 2 +- ...mberComparable.cs => IMemberComparable.cs} | 2 +- ...MemberComparer[T].cs => MemberComparer.cs} | 2 +- LibationWinForms/SortableBindingList2[T].cs | 4 +- 5 files changed, 38 insertions(+), 33 deletions(-) rename LibationWinForms/{IObjectMemberComparable.cs => IMemberComparable.cs} (79%) rename LibationWinForms/{ObjectMemberComparer[T].cs => MemberComparer.cs} (85%) diff --git a/FileManager/PictureStorage.cs b/FileManager/PictureStorage.cs index f9f5a35d..8c143dcf 100644 --- a/FileManager/PictureStorage.cs +++ b/FileManager/PictureStorage.cs @@ -34,12 +34,10 @@ namespace FileManager private static string getPath(PictureDefinition def) => Path.Combine(ImagesDirectory, $"{def.PictureId}{def.Size}.jpg"); - static Task backgroundDownloader; - static PictureStorage() { - backgroundDownloader = new Task(BackgroundDownloader); - backgroundDownloader.Start(); + new Task(BackgroundDownloader, TaskCreationOptions.LongRunning) + .Start(); } public static event EventHandler PictureCached; @@ -49,39 +47,45 @@ namespace FileManager private static Dictionary defaultImages { get; } = new Dictionary(); public static (bool isDefault, byte[] bytes) GetPicture(PictureDefinition def) { - if (cache.ContainsKey(def)) - return (false, cache[def]); - - var path = getPath(def); - - if (File.Exists(path)) + lock (cache) { - cache[def] = File.ReadAllBytes(path); - return (false, cache[def]); - } + if (cache.ContainsKey(def)) + return (false, cache[def]); - DownloadQueue.Add(def); - return (true, getDefaultImage(def.Size)); + var path = getPath(def); + + if (File.Exists(path)) + { + cache[def] = File.ReadAllBytes(path); + return (false, cache[def]); + } + + DownloadQueue.Add(def); + return (true, getDefaultImage(def.Size)); + } } public static byte[] GetPictureSynchronously(PictureDefinition def) { - if (!cache.ContainsKey(def) || cache[def] == null) + lock (cache) { - var path = getPath(def); - byte[] bytes; - - if (File.Exists(path)) - bytes = File.ReadAllBytes(path); - else + if (!cache.ContainsKey(def) || cache[def] == null) { - bytes = downloadBytes(def); - saveFile(def, bytes); - } + var path = getPath(def); + byte[] bytes; - cache[def] = bytes; + if (File.Exists(path)) + bytes = File.ReadAllBytes(path); + else + { + bytes = downloadBytes(def); + saveFile(def, bytes); + } + + cache[def] = bytes; + } + return cache[def]; } - return cache[def]; } public static void SetDefaultImage(PictureSize pictureSize, byte[] bytes) @@ -100,7 +104,8 @@ namespace FileManager var bytes = downloadBytes(def); saveFile(def, bytes); - cache[def] = bytes; + lock (cache) + cache[def] = bytes; PictureCached?.Invoke(nameof(PictureStorage), new PictureCachedEventArgs { Definition = def, Picture = bytes }); } diff --git a/LibationWinForms/GridEntry.cs b/LibationWinForms/GridEntry.cs index 558d22ec..032828b9 100644 --- a/LibationWinForms/GridEntry.cs +++ b/LibationWinForms/GridEntry.cs @@ -10,7 +10,7 @@ using System.Linq; namespace LibationWinForms { - internal class GridEntry : AsyncNotifyPropertyChanged, IObjectMemberComparable + internal class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable { #region implementation properties // hide from public fields from Data Source GUI with [Browsable(false)] diff --git a/LibationWinForms/IObjectMemberComparable.cs b/LibationWinForms/IMemberComparable.cs similarity index 79% rename from LibationWinForms/IObjectMemberComparable.cs rename to LibationWinForms/IMemberComparable.cs index bfacb0cd..bbc6471e 100644 --- a/LibationWinForms/IObjectMemberComparable.cs +++ b/LibationWinForms/IMemberComparable.cs @@ -3,7 +3,7 @@ using System.Collections; namespace LibationWinForms { - internal interface IObjectMemberComparable + internal interface IMemberComparable { IComparer GetMemberComparer(Type memberType); object GetMemberValue(string memberName); diff --git a/LibationWinForms/ObjectMemberComparer[T].cs b/LibationWinForms/MemberComparer.cs similarity index 85% rename from LibationWinForms/ObjectMemberComparer[T].cs rename to LibationWinForms/MemberComparer.cs index 3024477e..1bca2c82 100644 --- a/LibationWinForms/ObjectMemberComparer[T].cs +++ b/LibationWinForms/MemberComparer.cs @@ -3,7 +3,7 @@ using System.ComponentModel; namespace LibationWinForms { - internal class ObjectMemberComparer : IComparer where T : IObjectMemberComparable + internal class MemberComparer : IComparer where T : IMemberComparable { public ListSortDirection Direction { get; set; } = ListSortDirection.Ascending; public string PropertyName { get; set; } diff --git a/LibationWinForms/SortableBindingList2[T].cs b/LibationWinForms/SortableBindingList2[T].cs index 23f9a6ad..c29d1f65 100644 --- a/LibationWinForms/SortableBindingList2[T].cs +++ b/LibationWinForms/SortableBindingList2[T].cs @@ -5,7 +5,7 @@ using System.ComponentModel; namespace LibationWinForms { - internal class SortableBindingList2 : BindingList where T : IObjectMemberComparable + internal class SortableBindingList2 : BindingList where T : IMemberComparable { private bool isSorted; private ListSortDirection listSortDirection; @@ -14,7 +14,7 @@ namespace LibationWinForms public SortableBindingList2() : base(new List()) { } public SortableBindingList2(IEnumerable enumeration) : base(new List(enumeration)) { } - private ObjectMemberComparer Comparer { get; } = new(); + private MemberComparer Comparer { get; } = new(); protected override bool SupportsSortingCore => true; protected override bool SupportsSearchingCore => true; protected override bool IsSortedCore => isSorted;