Async Task引发内存泄漏,求Fbx导入流程的泄漏修复方案
异步FBX导入中的MaterialInfoBank内存泄漏问题
问题场景与现象
我实现了ImportFbxAsync()方法,流程如下:
- 先异步启动
BuildMaterialBankAsync()(不立即使用await,因该操作耗时较长) - 接着执行
BuildScene()任务 - 最后等待
BuildMaterialBankAsync()的结果再推进后续操作
但存在以下问题:当fbxPath == null(导入取消)或者ShowImportOptions(importOptions)触发方法提前返回/终止时,BuildMaterialBankAsync()生成的MaterialInfoBank实例会导致内存泄漏,且泄漏的内存会持续到应用整个生命周期。
通过Rider内存分析工具的前后快照对比,已确认该泄漏现象。
相关代码
FbxImport类核心代码
public class FbxImport { public static async Task ImportFbxAsync(StudioViewModel studioView) { studioView.IsBackgroundLoading = true; CancellationTokenSource cancellationTokenSource = new(); // 异步构建材质库 var materialBankTask = BuildMaterialBankAsync(studioView, cancellationTokenSource.Token); var fbxPath = GetFbxFilePath(studioView); if (fbxPath == null) { Logger.Log(0, "Import canceled.", "Import canceled"); studioView.IsBackgroundLoading = false; // 取消材质库构建任务 cancellationTokenSource.Cancel(); return; } Logger.Log(17, fbxPath, "Importing..."); // 目前未检测到BuildScene存在内存泄漏 var fBXScene = await BuildScene(studioView, fbxPath); // 等待材质库构建完成 var materialBankResult = await materialBankTask; try { if (fBXScene == null) { Logger.Log(18, "Fbx Import Failed ", "Fbx Import Failed ", false); return; } var importOptions = CreateImportOptions( studioView.TargetedGame, fBXScene, materialBankResult ); // 可能在此处取消导入 if (ShowImportOptions(importOptions)) { await ProcessBones(studioView, importOptions, fBXScene); await ProcessMeshes(studioView, importOptions, fBXScene); await ProcessDummies(studioView, importOptions, fBXScene); Logger.Log(19, $"{fbxPath} \n imported successfully", " Successful Import."); } else { Logger.Log(0, "Import canceled.", "Import Canceled"); } } catch (Exception ex) { Logger.Log(0, ex.ToString(), "Import Faild", false); } finally { fBXScene?.Dispose(); materialBankResult?.Dispose(); materialBankTask?.Dispose(); studioView.IsBackgroundLoading = false; } } public static async Task<MaterialInfoBank> BuildMaterialBankAsync( StudioViewModel studioView, CancellationToken cancellationToken ) { var filePath = $"IncludeResources\\MaterialBanks\\Bank{studioView.TargetedGame}.xml"; return await Task.Run( () => MaterialInfoBank.ReadFromXML(filePath), cancellationToken ); } }
MaterialInfoBank类结构(无所有权)
public Dictionary<string, MaterialDef> MaterialDefs = new Dictionary<string, MaterialDef>(); public Dictionary<string, XmlStructDef> GXItemStructs = new Dictionary<string, XmlStructDef>(); public Dictionary<string, List<byte[]>> DefaultGXItemDataExamples = new Dictionary<string, List<byte[]>>();
已尝试的解决方法
我尝试给MaterialInfoBank添加了IDisposable释放模式,清理内部字典并置空,但内存泄漏问题仍未解决:
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // 清理托管状态 MaterialDefs.Clear(); GXItemStructs.Clear(); DefaultGXItemDataExamples.Clear(); MaterialDefs = null; GXItemStructs = null; DefaultGXItemDataExamples = null; } disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); }
求助需求
寻求修复该内存泄漏问题的具体方法或相关技术指导。
内容的提问来源于stack exchange,提问作者ahmed moussa
相关产品推荐
相关产品推荐

