Объект WaveOut
, которому «принадлежит» делегат WaveCallbackInfo.FunctionCallback()
, удаляется и мусор собирается в конце using
-блока. Похоже, ваш цикл while
не предоставляет никакой защиты от использования делегата после этого (звучит так, будто нативный код вызывает его, странная архитектура).
Вы можете использовать ManualResetEvent для достижения ожидания:
// lifetime as long as your application
static WaveCallbackInfo callbackInfo = WaveCallbackInfo.FunctionCallback();
Тогда внутри вашего метода
var mre = new ManualResetEvent(false); // created unsignaled
using (var rdr = new Mp3FileReader(FileName))
using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new BlockAlignReductionStream(wavStream))
using (var waveOut = new WaveOut(callbackInfo))
{
waveOut.Init(baStream);
waveOut.Play();
waveOut.PlaybackStopped += (sender,e) => { mre.Set(); };
mre.WaitOne();
}
Редактировать : нативный код требует какого-либо дескриптора для запуска. Это фактически означает, что дескриптор никогда не может исчезнуть , пока собственный код все еще работает.
В настоящее время проблема с этим кодом заключается в том, что трудно сказать, когда (если вообще когда-либо) вам потребуется создать НОВЫЙ информационный объект обратного вызова. Вы также можете попробовать:
static WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
static ManualResetEvent waveEvent = new ManualResetEvent(false);
static Player()
{
waveOut.PlaybackStopped += (sender, e) => { waveEvent.Set(); };
}
Затем в вашем методе (предполагается, что waveOut можно инициализировать более одного раза):
waveEvent.Reset();
using (var rdr = new Mp3FileReader(FileName))
using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new BlockAlignReductionStream(wavStream))
{
waveOut.Init(baStream);
waveOut.Play();
waveEvent.WaitOne();
}