gpt4 book ai didi

c# - 正在收集回调委托(delegate)?

转载 作者:可可西里 更新时间:2023-11-01 02:58:48 25 4
gpt4 key购买 nike

一直在使用 FMOD 进行 C# 游戏开发,我很早就遇到了一个障碍,我似乎无法绕过。我想做一些分支音频的东西并将一些游戏 Action 同步到节拍等,所以我尝试将同步点添加到我的音乐轨道中。这是代码:

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;
}
}

然后……

m = new Music(MUS_TUTORIAL);  //m is static
m.Load();
m.Play();

这首歌加载并播放得很好......直到它达到我添加的 500 毫秒同步点。此时,VC# 从 FMOD.EventSystem.update() 中吐出以下错误:

A callback was made on a garbage collected delegate of type 'Game!FMOD.CHANNEL_CALLBACK::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

所以不知何故,FMOD 正在失去对我传递给它的委托(delegate)的跟踪。持有委托(delegate)的 Music 实例尚未被垃圾回收——我现在将它存储在一个静态变量中——但我也尝试过使用静态方法无济于事。如果我禁用 CallbackOnCollectedDelegate MDA,错误将变为空引用异常,因此 MDA 没有错误。我想我一定是不完全理解 FMOD 在这里做什么。

是否有任何 C# + FMOD 专家能够看出我的错误?

最佳答案

    channel.setCallback(channelCallback);

这就是问题陈述。 FMod 是非托管代码。您正在此处创建委托(delegate)对象并将其传递给非托管代码。问题是,垃圾收集器无法跟踪 native 代码持有的引用。下一次垃圾回收将找到没有 对该对象的引用并将其回收。当 native 代码进行回调时,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);
}

您需要从 FMod 包装器代码中找到实际的委托(delegate)类型,我只是猜测“SomeDelegateType”。

关于c# - 正在收集回调委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7302045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com