Mat*_*att 18 c# delegates garbage-collection fmod
一直在忙着用FMOD进行C#游戏开发,我很早就遇到了麻烦,我似乎无法绕过.我想做一些分支音频的东西并将一些游戏动作同步到节拍等等,所以我尝试将同步点添加到我的音乐曲目中.这是代码:
public class Music
{
private Sound music;
private Channel channel;
private IntPtr syncPtr;
public string File { get; private set; }
public Music(string file)
{
File = file;
}
public void Load()
{
music = new Sound();
Audio.System.createSound(File, MODE.HARDWARE, ref music);
}
public void Unload()
{
music.release();
}
public virtual void Play()
{
Audio.System.playSound(channel == null ? CHANNELINDEX.FREE : CHANNELINDEX.REUSE, music, false, ref channel);
music.addSyncPoint(500, TIMEUNIT.MS, "wooo", ref syncPtr);
channel.setCallback(channelCallback);
}
private RESULT channelCallback(IntPtr channelraw, CHANNEL_CALLBACKTYPE type, IntPtr commanddata1, IntPtr commanddata2)
{
if (type == CHANNEL_CALLBACKTYPE.SYNCPOINT)
Console.WriteLine("sync!");
return RESULT.OK;
}
}
Run Code Online (Sandbox Code Playgroud)
然后...
m = new Music(MUS_TUTORIAL); //m is static
m.Load();
m.Play();
Run Code Online (Sandbox Code Playgroud)
这首歌加载并播放正常...直到它达到我添加的500毫秒同步点.此时,VC#从FMOD.EventSystem.update()中吐出以下错误:
在"Game!FMOD.CHANNEL_CALLBACK :: Invoke"类型的垃圾收集委托上进行了回调.这可能会导致应用程序崩溃,损坏和数据丢失.将委托传递给非托管代码时,托管应用程序必须将它们保持活动状态,直到确保它们永远不会被调用.
所以不知何故FMOD正在失去我通过它的代表的踪迹.持有委托的Music实例并没有被垃圾收集 - 我现在将它存储在一个静态变量中 - 但我尝试使用静态方法也无济于事.如果我禁用CallbackOnCollectedDelegate MDA,则错误将成为空引用异常,因此MDA不会出错.我想我必须完全不了解FMOD在这里做了什么.
任何C#+ FMOD大师都能看到我的错误吗?
Han*_*ant 30
channel.setCallback(channelCallback);
Run Code Online (Sandbox Code Playgroud)
这是问题陈述.FMod是非托管代码.您正在此处创建委托对象并将其传递给非托管代码.问题是,垃圾收集器无法跟踪本机代码所持有的引用.接下来的垃圾收集会发现没有对象引用和收集.当本机代码进行回调时Kaboom.
你需要自己保留一个引用,这样就不会发生:
public class Music
{
private SomeDelegateType callback
//...
public Music(string file)
{
File = file;
callback = new SomeDelegateType(channelCallback);
}
public virtual void Play()
{
Audio.System.playSound(channel == null ? CHANNELINDEX.FREE : CHANNELINDEX.REUSE, music, false, ref channel);
music.addSyncPoint(500, TIMEUNIT.MS, "wooo", ref syncPtr);
channel.setCallback(callback);
}
Run Code Online (Sandbox Code Playgroud)
你需要从FMod包装器代码中找到实际的委托类型,我只是猜到了"SomeDelegateType".