如何在使用using变量时返回MemoryStream?技术咨询
在using场景下正确返回MemoryStream的解决方案
首先得明确核心问题:using语句块结束时会自动调用对象的Dispose()方法,如果直接返回using块内创建的MemoryStream,外部拿到的流已经被释放,根本无法读取使用。下面给你两种实用的解决思路:
方案1:移除返回流的using语句,由调用方负责释放
如果你的方法需要直接返回MemoryStream,就不能用using包裹这个要返回的流,改用try-catch块确保出错时能正确释放资源,正常返回时把流的控制权交给调用方:
String ICallbackEventHandler.GetCallbackResult() { var stream = new MemoryStream(); try { this._synth.Rate = this.Rate; this._synth.Volume = this.Volume; this._synth.SetOutputToWaveStream(stream); string sText = this.Context.Items["data"].ToString(); this._synth.Speak(sText); stream.Seek(0, SeekOrigin.Begin); var nMp3Stream = new MemoryStream(); try { using (var rdr = new WaveFileReader(stream)) { // 这里添加Wave转MP3的逻辑,比如使用LameMP3Writer // 示例:using (var writer = new LameMP3Writer(nMp3Stream, rdr.WaveFormat, 128)) { rdr.CopyTo(writer); } } nMp3Stream.Seek(0, SeekOrigin.Begin); // 这里按你的方法返回类型,把流转成Base64字符串返回 return Convert.ToBase64String(nMp3Stream.ToArray()); } catch { nMp3Stream.Dispose(); throw; } } catch { stream.Dispose(); throw; } }
方案2:复制流内容到新的MemoryStream后返回
如果你不想让调用方处理资源释放,或者必须保留原流的using包裹,可以把原流的内容复制到一个未被using包裹的新流里,返回这个新流(或者它的内容):
String ICallbackEventHandler.GetCallbackResult() { using (var stream = new MemoryStream()) { this._synth.Rate = this.Rate; this._synth.Volume = this.Volume; this._synth.SetOutputToWaveStream(stream); string sText = this.Context.Items["data"].ToString(); this._synth.Speak(sText); stream.Seek(0, SeekOrigin.Begin); using (var rdr = new WaveFileReader(stream)) { var outputStream = new MemoryStream(); // 把读取到的Wave数据复制到新流 rdr.CopyTo(outputStream); outputStream.Seek(0, SeekOrigin.Begin); // 转成Base64字符串返回,外部拿到字符串后可以再转回流 return Convert.ToBase64String(outputStream.ToArray()); } } }
额外提醒
- 如果你的方法返回类型是
MemoryStream,一定要确保返回的流没有被Dispose,调用方需要在使用完后手动调用Dispose(),或者用using包裹调用代码。 - 如果返回的是字符串(比如Base64),就不用顾虑流释放的问题,因为字符串是独立的数值,和原流的生命周期无关。
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

