Skip to content

Commit 55264a9

Browse files
Jack251970TBM13
authored andcommitted
Merge pull request Flow-Launcher#3990 from Flow-Launcher/internalization_memory_leak
Remove old dictionaries references to fix possible memory leak
1 parent 61fb5a8 commit 55264a9

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

Flow.Launcher.Core/Resource/Internationalization.cs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
namespace Flow.Launcher.Core.Resource
1616
{
17-
public class Internationalization
17+
public class Internationalization : IDisposable
1818
{
1919
private static readonly string ClassName = nameof(Internationalization);
2020

@@ -30,6 +30,7 @@ public class Internationalization
3030
private readonly List<string> _languageDirectories = [];
3131
private readonly List<ResourceDictionary> _oldResources = [];
3232
private static string SystemLanguageCode;
33+
private readonly SemaphoreSlim _langChangeLock = new(1, 1);
3334

3435
public Internationalization(Settings settings)
3536
{
@@ -185,20 +186,33 @@ private static Language GetLanguageByLanguageCode(string languageCode)
185186

186187
private async Task ChangeLanguageAsync(Language language, bool updateMetadata = true)
187188
{
188-
// Remove old language files and load language
189-
RemoveOldLanguageFiles();
190-
if (language != AvailableLanguages.English)
189+
await _langChangeLock.WaitAsync();
190+
191+
try
191192
{
192-
LoadLanguage(language);
193-
}
193+
// Remove old language files and load language
194+
RemoveOldLanguageFiles();
195+
if (language != AvailableLanguages.English)
196+
{
197+
LoadLanguage(language);
198+
}
194199

195-
// Change culture info
196-
ChangeCultureInfo(language.LanguageCode);
200+
// Change culture info
201+
ChangeCultureInfo(language.LanguageCode);
197202

198-
if (updateMetadata)
203+
if (updateMetadata)
204+
{
205+
// Raise event for plugins after culture is set
206+
await Task.Run(UpdatePluginMetadataTranslations);
207+
}
208+
}
209+
catch (Exception e)
199210
{
200-
// Raise event for plugins after culture is set
201-
await Task.Run(UpdatePluginMetadataTranslations);
211+
API.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e);
212+
}
213+
finally
214+
{
215+
_langChangeLock.Release();
202216
}
203217
}
204218

@@ -233,6 +247,7 @@ private void RemoveOldLanguageFiles()
233247
{
234248
dicts.Remove(r);
235249
}
250+
_oldResources.Clear();
236251
}
237252

238253
private void LoadLanguage(Language language)
@@ -342,5 +357,15 @@ public static void UpdatePluginMetadataTranslations()
342357
}
343358

344359
#endregion
360+
361+
#region IDisposable
362+
363+
public void Dispose()
364+
{
365+
RemoveOldLanguageFiles();
366+
_langChangeLock.Dispose();
367+
}
368+
369+
#endregion
345370
}
346371
}

Flow.Launcher/App.xaml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public partial class App : IDisposable, ISingleInstanceApp
3838
private static Settings _settings;
3939
private static MainWindow _mainWindow;
4040
private readonly MainViewModel _mainVM;
41+
private readonly Internationalization _internationalization;
4142

4243
// To prevent two disposals running at the same time.
4344
private static readonly object _disposingLock = new();
@@ -91,6 +92,7 @@ public App()
9192
API = Ioc.Default.GetRequiredService<IPublicAPI>();
9293
_settings.Initialize();
9394
_mainVM = Ioc.Default.GetRequiredService<MainViewModel>();
95+
_internationalization = Ioc.Default.GetRequiredService<Internationalization>();
9496
}
9597
catch (Exception e)
9698
{
@@ -171,7 +173,7 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () =>
171173
Win32Helper.EnableWin32DarkMode(_settings.ColorScheme);
172174

173175
// Initialize language before portable clean up since it needs translations
174-
await Ioc.Default.GetRequiredService<Internationalization>().InitializeLanguageAsync();
176+
await _internationalization.InitializeLanguageAsync();
175177

176178
API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");
177179
API.LogInfo(ClassName, $"Runtime info:{ErrorReporting.RuntimeInfo()}");
@@ -308,6 +310,7 @@ protected virtual void Dispose(bool disposing)
308310
// since some resources owned by the thread need to be disposed.
309311
_mainWindow?.Dispatcher.Invoke(_mainWindow.Dispose);
310312
_mainVM?.Dispose();
313+
_internationalization.Dispose();
311314
}
312315

313316
API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------");

0 commit comments

Comments
 (0)