.NET MAUI(C#)应用垃圾回收持续运行,如何解决?
.NET MAUI 启动后GC持续运行的问题排查与修复
你的核心问题出在无限循环导致的持续内存分配,再加上代码里的几个小问题,让GC根本停不下来。
问题分析
- 无限循环:
RepositoryVoid方法的for循环里写了i--,直接导致循环变量永远卡在1,无限调用LoadMauiAssetLessons,反复创建异步任务和临时对象,内存被持续占用,GC只能频繁回收。 - 数组索引越界风险:
LessonsList是长度为17的数组(索引范围0-16),但循环里i从1到17,直接用i作为索引会触发越界异常。 - async void的隐患:
LoadMauiAssetLessons用了async void,非事件场景下这种写法会导致异常无法被正确捕获,还可能引发线程调度问题,增加内存管理的不确定性。 - 重复反序列化:每次加载JSON都反序列化两次,额外创建了不必要的对象,加重GC负担。
修复后的代码
修正后的Repo类
internal class Repo { public Lessons[] LessonsList = new Lessons[17]; // 改为async Task,方便外部调用时等待初始化完成 public async Task InitializeAsync() { for (int i = 1; i < 18; i++) { // 数组索引从0开始,用i-1对应正确位置 await LoadMauiAssetLessons($"{i}.json", i - 1); } } // 把async void改为async Task,避免异步场景的异常和线程问题 private async Task LoadMauiAssetLessons(string path, int index) { try { using var stream = await FileSystem.OpenAppPackageFileAsync(path); using var reader = new StreamReader(stream); var contents = await reader.ReadToEndAsync(); // 用异步读取更适配MAUI的IO模型 var lesson = JsonSerializer.Deserialize<Lessons>(contents); if (lesson != null) { LessonsList[index] = lesson; } } catch (FileNotFoundException ex) { Debug.WriteLine($"文件未找到: {ex.Message}"); } catch (Exception ex) { Debug.WriteLine($"加载失败: {ex.Message}"); } } }
调用示例(比如在App.xaml.cs或ViewModel中)
var repo = new Repo(); await repo.InitializeAsync();
额外优化建议
- 用List
替代数组 :数组长度固定,List更灵活,能避免手动计算索引的越界问题。 - 合并JSON文件:如果内容不会动态变化,可将17个JSON合并为一个文件,减少IO操作和对象创建次数。
- 启用发布版Trim功能:在发布模式下开启.NET的Trim功能,可移除不必要的代码,降低内存占用(注意处理反射相关的兼容问题)。
内容的提问来源于stack exchange,提问作者Oskar Kacala
相关产品推荐
相关产品推荐

