UWP中AudioGraph启动后内存持续增长问题求助
解决AudioGraph启动后内存持续增长的问题
我之前在使用UWP的AudioGraph时也碰到过类似的内存泄漏问题,结合你的代码来看,核心问题是多个音频相关对象没有被正确释放,每次点击按钮都会创建新实例,旧实例却一直留在内存中。下面是具体的修复方案:
1. 清理重复创建的节点实例
每次点击按钮创建新的音频节点前,一定要先释放旧的节点资源,避免内存堆积:
针对电脑语音播放的按钮事件(BtnComputerVoice_Click)
在创建新的mediaInput和frameOutputNode前,先检查并释放旧实例:
private async void BtnComputerVoice_Click(object sender, RoutedEventArgs e) { graph.Stop(); // 释放旧的媒体输入节点 if (mediaInput != null) { mediaInput.Dispose(); mediaInput = null; } // 释放旧的帧输出节点 if (frameOutputNode != null) { frameOutputNode.Dispose(); frameOutputNode = null; } // 释放旧的MediaSource if (mediaVoice != null) { mediaVoice.Dispose(); mediaVoice = null; } graph.ResetAllNodes(); // 使用using自动释放SpeechSynthesizer using (var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer()) { SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); mediaVoice = MediaSource.CreateFromStream(stream, stream.ContentType); CreateMediaSourceAudioInputNodeResult fileInputResult = await graph.CreateMediaSourceAudioInputNodeAsync(mediaVoice); if (MediaSourceAudioInputNodeCreationStatus.Success != fileInputResult.Status) { stream.Dispose(); // 失败时也要释放流资源 return; } mediaInput = fileInputResult.Node; mediaInput.AddOutgoingConnection(deviceOutput); frameOutputNode = graph.CreateFrameOutputNode(); mediaInput.AddOutgoingConnection(frameOutputNode); frameOutputNode.OutgoingGain = 4; graph.Start(); // 播放完成后自动释放流 mediaInput.MediaSourceCompleted += (s, args) => { stream.Dispose(); }; } }
针对麦克风输入的按钮事件(BtnMicrophone_Click)
新增类成员AudioDeviceInputNode deviceInput;,然后在创建新实例前释放旧的:
// 类成员添加 AudioDeviceInputNode deviceInput; private async void BtnMicrophone_Click(object sender, RoutedEventArgs e) { if (graph != null) { graph.Stop(); // 释放旧的麦克风输入节点 if (deviceInput != null) { deviceInput.Dispose(); deviceInput = null; } // 释放旧的帧输出节点 if (frameOutputNode != null) { frameOutputNode.Dispose(); frameOutputNode = null; } graph.ResetAllNodes(); } CreateAudioDeviceInputNodeResult fileInputResult = await graph.CreateDeviceInputNodeAsync(Windows.Media.Capture.MediaCategory.Speech); if (AudioDeviceNodeCreationStatus.Success != fileInputResult.Status) { return; } deviceInput = fileInputResult.DeviceInputNode; frameOutputNode = graph.CreateFrameOutputNode(); deviceInput.AddOutgoingConnection(frameOutputNode); graph.Start(); }
2. 关键注意事项
- 使用
using语句管理短期对象:比如SpeechSynthesizer这类只在方法内使用的对象,用using可以确保它在方法结束时自动释放,避免资源残留。 - 流资源的强制释放:
SpeechSynthesisStream无论创建节点成功与否,都要手动调用Dispose,它不会随MediaSource自动回收。 - 节点事件的清理:如果给节点添加了事件监听(比如
MediaSourceCompleted),若后续不再需要,记得移除监听,防止引用导致对象无法被GC回收。 - Graph重置顺序:先手动释放所有节点资源,再调用
graph.ResetAllNodes(),避免节点资源在Graph中残留。
修复后,你可以再次用Visual Studio的诊断工具观测内存变化,正常情况下播放完成或停止麦克风后,内存会逐步回落,不会持续增长。
内容的提问来源于stack exchange,提问作者Ives
相关产品推荐
相关产品推荐

