IrrKlang声音库和停止事件线程

时间:2017-01-21 10:58:28

标签: multithreading winforms audio thread-safety irrklang

我有一个关于使用外部c ++库(irrKlang.dll)的问题,这是一个音频播放引擎。现在,问题在于当我从中获取SoundStopped事件并在主窗体中执行操作时,会出现各种与堆栈相关的错误。让我展示一下代码:

namespace WindowsFormsApplication4

{
    public class IsoundFinished : ISoundStopEventReceiver
    {
        public delegate void OnSoundStoppedEventHandler(object source, EventArgs e);
        public event OnSoundStoppedEventHandler IStopped;

        public void OnSoundStopped(ISound iSound, StopEventCause reason, object userData)
        {
            if (reason.ToString() == "SoundFinishedPlaying")
                IStopped?.Invoke(this, EventArgs.Empty);
        }
    }
}

这是我进行自定义操作的扩展类(例如 - 如果声音已完成,则引发事件......)我正在创建它的实例,以便在我的主Form1类中公开事件操作:

IsoundFinished iStopReceiver = new IsoundFinished();

现在在我的主窗体中,我在Form1()方法中有这一行,就在我的InitializeComponent()下面:

iStopReceiver.IStopped += new soundFinished.OnSoundStoppedEventHandler(OnStopped);

订阅事件处理程序。最后 - 我的OnStopped()方法,当歌曲结束播放时应该做的事情 - 它在同一个Form1上:

 private void OnStopped(object sender, EventArgs e)
        {            
            if (InvokeRequired)
            {
                Invoke(new Action<object, EventArgs>(OnStopped), sender, e);
                return;
            }            

            btnStop1.PerformClick();
        }

我的Stop1按钮方法(对于那些使用IrrKlang的人)ISound.Stop();以及更多代码行,处理播放列表的显示等等。虽然我从主UI线程调用它 - 这应该为我提供一定程度的线程错位保护,但是出现了各种错误,主要是

Cannot evaluate expression because a native frame is on the top of the call stack.

当然,如果我没有事件处理程序,ISound.Stop();像它应该的那样从发动机上掉下声音。我知道线程发生了一些错误,但我无法弄清楚发生了什么。如果有人会给我一些提示,我会非常感激。

1 个答案:

答案 0 :(得分:0)

好吧,我自己已经解决了!它是关于理解线程在Visual C#中如何工作的全部内容。问题是这样的:我实际上是在播放我的audioengine触发事件的后台线程 - 所以&#39;直到我在主UI线程中的INVOKE之后执行了一个动作,后台线程与整个irrKlang引擎一起暂停。它无法正常清除自己,因此它的调用堆栈被阻塞了!

使用BEGININVOKE解决了这个问题,因为它没有暂停后台任务。它允许它运行。关于this回答的图表给了我一些我正在寻找的信息。 也许有人也需要这个答案,很高兴我帮助自己:P

private void OnStopped(object sender, EventArgs e)
        {            
            if (InvokeRequired)
            {
                BeginInvoke(new Action<object, EventArgs>(OnStopped), sender, e);
                return;
            }            

            btnStop1.PerformClick();                
        }