使用NAudio的WaveOutEvent播放WAV文件触发NullReferenceException问题排查
NAudio播放WAV文件时出现NullReferenceException异常问题
问题场景
在WPF应用中使用NAudio的WaveOutEvent播放MP3和WAV文件,MP3播放正常,但播放WAV文件时,调用player.Play()后,NAudio.Core抛出NullReferenceException,提示“未将对象引用设置到对象的实例”。
代码示例
using (AudioFileReader afr = new AudioFileReader(_filename)) { OffsetSampleProvider osp = new OffsetSampleProvider(afr); osp.SkipOver = currentCursorPosition; osp.Take = PlaybackDuration; WaveOutEvent player = new WaveOutEvent(); player.Init(osp); player.Play(); }
异常信息
- Exception.Source: NAudio.Core
- Exception.StackTrace: 在**NAudio.Wave.WaveFileReader.get_Position()**处
- 模块版本: NAudio.Core.dll 2.01.0.0
问题原因
核心原因是AudioFileReader被using语句提前释放。WaveOutEvent是异步播放,using块会在player.Play()调用后立即执行Dispose,此时后台播放线程仍在运行。处理WAV文件时,AudioFileReader内部的WaveFileReader实例被释放后变为null,线程读取数据调用其Position属性时触发空引用异常。
MP3播放正常是因为AudioFileReader处理MP3时使用的Mp3FileReader内部实现不会在Dispose后立即导致核心读取对象失效,和WAV的WaveFileReader资源释放逻辑不同。
解决方法
方法1:移除using语句,通过播放结束事件手动释放资源
确保AudioFileReader在播放全程保持有效,监听PlaybackStopped事件,在播放结束后再释放相关资源:
var afr = new AudioFileReader(_filename); var osp = new OffsetSampleProvider(afr); osp.SkipOver = currentCursorPosition; osp.Take = PlaybackDuration; var player = new WaveOutEvent(); player.PlaybackStopped += (s, e) => { player.Dispose(); afr.Dispose(); }; player.Init(osp); player.Play();
方法2:避免提前释放音频读取器
绝对不要将AudioFileReader放在using块中,因为异步播放时,using块的生命周期远短于播放线程的运行周期,会导致资源提前释放引发异常。
内容的提问来源于stack exchange,提问作者Aaginor
相关产品推荐
相关产品推荐

