Skip to content

Commit 5d843ec

Browse files
authored
Merge pull request #3990 from Flow-Launcher/internalization_memory_leak
Remove old dictionaries references to fix possible memory leak
2 parents 1689571 + 0f6245a commit 5d843ec

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

Flow.Launcher.Core/Resource/Internationalization.cs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.IO;
@@ -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

@@ -257,6 +271,7 @@ private void RemoveOldLanguageFiles()
257271
{
258272
dicts.Remove(r);
259273
}
274+
_oldResources.Clear();
260275
}
261276

262277
private void LoadLanguage(Language language)
@@ -368,5 +383,15 @@ public static void UpdatePluginMetadataTranslations()
368383
}
369384

370385
#endregion
386+
387+
#region IDisposable
388+
389+
public void Dispose()
390+
{
391+
RemoveOldLanguageFiles();
392+
_langChangeLock.Dispose();
393+
}
394+
395+
#endregion
371396
}
372397
}

Flow.Launcher/App.xaml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public partial class App : IDisposable, ISingleInstanceApp
4545
private static Settings _settings;
4646
private static MainWindow _mainWindow;
4747
private readonly MainViewModel _mainVM;
48+
private readonly Internationalization _internationalization;
4849

4950
// To prevent two disposals running at the same time.
5051
private static readonly object _disposingLock = new();
@@ -107,6 +108,7 @@ public App()
107108
API = Ioc.Default.GetRequiredService<IPublicAPI>();
108109
_settings.Initialize();
109110
_mainVM = Ioc.Default.GetRequiredService<MainViewModel>();
111+
_internationalization = Ioc.Default.GetRequiredService<Internationalization>();
110112
}
111113
catch (Exception e)
112114
{
@@ -193,7 +195,7 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () =>
193195
Win32Helper.EnableWin32DarkMode(_settings.ColorScheme);
194196

195197
// Initialize language before portable clean up since it needs translations
196-
await Ioc.Default.GetRequiredService<Internationalization>().InitializeLanguageAsync();
198+
await _internationalization.InitializeLanguageAsync();
197199

198200
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
199201

@@ -421,6 +423,7 @@ protected virtual void Dispose(bool disposing)
421423
_mainWindow?.Dispatcher.Invoke(_mainWindow.Dispose);
422424
_mainVM?.Dispose();
423425
DialogJump.Dispose();
426+
_internationalization.Dispose();
424427
}
425428

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

0 commit comments

Comments
 (0)