Skip to content

Commit 080bf29

Browse files
committed
Fix race conditions for theme import and config save
1 parent d7d5f44 commit 080bf29

File tree

4 files changed

+63
-52
lines changed

4 files changed

+63
-52
lines changed

src/AppContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ private void OnApplicationExit(object sender, EventArgs e)
126126
notifyIcon.Visible = false;
127127
}
128128

129+
JsonConfig.SaveConfig();
129130
ipcManager?.Dispose();
130131
}
131132
}

src/ImportDialog.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
using System;
66
using System.Collections.Generic;
7-
using System.Drawing;
87
using System.IO;
98
using System.Threading.Tasks;
109
using System.Windows.Forms;
@@ -90,8 +89,11 @@ private void UpdateTotalPercentage(int themePercentage)
9089

9190
private void OnFormClosing(object sender, FormClosingEventArgs e)
9291
{
93-
ThemeLoader.taskbarHandle = IntPtr.Zero;
9492
ThemeManager.importMode = false;
93+
if (thumbnailsLoaded)
94+
{
95+
ThemeLoader.taskbarHandle = IntPtr.Zero;
96+
}
9597
}
9698
}
9799
}

src/JsonConfig.cs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System;
88
using System.ComponentModel;
99
using System.IO;
10-
using System.Threading.Tasks;
1110
using System.Windows.Forms;
1211

1312
namespace WinDynamicDesktop
@@ -59,6 +58,7 @@ class JsonConfig
5958
private static System.Timers.Timer autoSaveTimer;
6059
private static bool restartPending = false;
6160
private static bool unsavedChanges;
61+
private static readonly object settingsFileLock = new object();
6262

6363
public static AppConfig settings = new AppConfig();
6464
public static bool firstRun = !File.Exists("settings.json");
@@ -93,9 +93,8 @@ public static void LoadConfig()
9393
}
9494

9595
unsavedChanges = false;
96-
autoSaveTimer = new System.Timers.Timer();
96+
autoSaveTimer = new System.Timers.Timer(1000);
9797
autoSaveTimer.AutoReset = false;
98-
autoSaveTimer.Interval = 1000;
9998
ConfigMigrator.UpdateObsoleteSettings();
10099

101100
settings.PropertyChanged += OnSettingsPropertyChanged;
@@ -108,48 +107,47 @@ public static void ReloadConfig()
108107
autoSaveTimer.Start();
109108
}
110109

110+
public static void SaveConfig()
111+
{
112+
if (!unsavedChanges)
113+
{
114+
return;
115+
}
116+
117+
unsavedChanges = autoSaveTimer.Enabled = false;
118+
string jsonText = JsonConvert.SerializeObject(settings, Formatting.Indented);
119+
lock (settingsFileLock)
120+
{
121+
File.WriteAllText("settings.json.tmp", jsonText);
122+
File.Move("settings.json.tmp", "settings.json", true);
123+
}
124+
}
125+
111126
public static bool IsNullOrEmpty(Array array)
112127
{
113128
return (array == null || array.Length == 0);
114129
}
115130

116131
private static void OnSettingsPropertyChanged(object sender, EventArgs e)
117132
{
118-
unsavedChanges = true;
119-
autoSaveTimer.Start();
133+
unsavedChanges = autoSaveTimer.Enabled = true;
120134
}
121135

122-
private static async void OnAutoSaveTimerElapsed(object sender, EventArgs e)
136+
private static void OnAutoSaveTimerElapsed(object sender, EventArgs e)
123137
{
124138
if (!restartPending && !unsavedChanges)
125139
{
126140
return;
127141
}
128142

129-
if (unsavedChanges)
130-
{
131-
unsavedChanges = false;
132-
autoSaveTimer.Elapsed -= OnAutoSaveTimerElapsed;
133-
134-
await Task.Run(() =>
135-
{
136-
string jsonText = JsonConvert.SerializeObject(settings, Formatting.Indented);
137-
File.WriteAllText("settings.json.tmp", jsonText);
138-
File.Move("settings.json.tmp", "settings.json", true);
139-
});
140-
}
143+
SaveConfig();
141144

142145
if (restartPending)
143146
{
144147
restartPending = false;
145148
System.Diagnostics.Process.Start(Application.ExecutablePath);
146149
Application.Exit();
147150
}
148-
else
149-
{
150-
autoSaveTimer.Elapsed += OnAutoSaveTimerElapsed;
151-
autoSaveTimer.Start();
152-
}
153151
}
154152
}
155153
}

src/ThemeDialog.cs

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -140,38 +140,48 @@ private void LoadThemes(List<ThemeConfig> themes, string activeTheme = null, str
140140

141141
foreach (ThemeConfig theme in themes.ToList())
142142
{
143-
try
143+
ListViewItem tempItem = this.Invoke(new Func<ListViewItem>(() =>
144144
{
145-
using (Image thumbnailImage = ThemeThumbLoader.GetThumbnailImage(theme, thumbnailSize, true))
145+
string itemText = ThemeManager.GetThemeName(theme);
146+
if (JsonConfig.settings.favoriteThemes != null &&
147+
JsonConfig.settings.favoriteThemes.Contains(theme.themeId))
146148
{
147-
this.Invoke(new Action(() =>
149+
itemText = "★ " + itemText;
150+
}
151+
ListViewItem newItem = listView1.Items.Add(itemText);
152+
newItem.Tag = theme.themeId;
153+
154+
if (activeTheme != null && activeTheme == theme.themeId)
155+
{
156+
newItem.Font = new Font(newItem.Font, FontStyle.Bold);
157+
}
158+
if (focusTheme == null || focusTheme == theme.themeId)
159+
{
160+
focusedItem = newItem;
161+
}
162+
163+
return newItem;
164+
}));
165+
166+
this.BeginInvoke(new Action<ListViewItem>((newItem) =>
167+
{
168+
try
169+
{
170+
using (Image thumbnailImage = ThemeThumbLoader.GetThumbnailImage(theme, thumbnailSize, true))
148171
{
149172
listView1.LargeImageList.Images.Add(thumbnailImage);
150-
string itemText = ThemeManager.GetThemeName(theme);
151-
if (JsonConfig.settings.favoriteThemes != null &&
152-
JsonConfig.settings.favoriteThemes.Contains(theme.themeId))
153-
{
154-
itemText = "★ " + itemText;
155-
}
156-
ListViewItem newItem = listView1.Items.Add(itemText,
157-
listView1.LargeImageList.Images.Count - 1);
158-
newItem.Tag = theme.themeId;
159-
160-
if (activeTheme != null && activeTheme == theme.themeId)
161-
{
162-
newItem.Font = new Font(newItem.Font, FontStyle.Bold);
163-
}
164-
if (focusTheme == null || focusTheme == theme.themeId)
165-
{
166-
focusedItem = newItem;
167-
}
168-
}));
173+
newItem.ImageIndex = listView1.LargeImageList.Images.Count - 1;
174+
}
169175
}
170-
}
171-
catch (OutOfMemoryException)
172-
{
173-
ThemeLoader.HandleError(new FailedToCreateThumbnail(theme.themeId));
174-
}
176+
catch (OutOfMemoryException)
177+
{
178+
ThemeLoader.HandleError(new FailedToCreateThumbnail(theme.themeId));
179+
if (ThemeManager.themeSettings.Find(t => t.themeId == theme.themeId) == null)
180+
{
181+
listView1.Items.RemoveAt(newItem.Index);
182+
}
183+
}
184+
}), tempItem);
175185
}
176186

177187
this.Invoke(new Action(() =>

0 commit comments

Comments
 (0)