回收代表正在收集? [英] Callback delegates being collected?

查看:176
本文介绍了回收代表正在收集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了C#游戏开发,FMOD一直在搞乱,我很早就遇到了麻烦,因为我似乎无法解决。我想做一些分支音频的东西,并将某些游戏操作同步到节拍等,因此我尝试将同步点添加到我的音乐曲目。这是代码:

Been messing around with FMOD for C# game development and I've hit a snag early on that I can't seem to get around. I want to do some branching audio stuff and sync some gameplay action to beats and such, so I've tried adding syncpoints to my music tracks. Here's code:

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();

歌曲加载并播放正常...直到它达到我添加的500ms同步点。此时,VC#在FMOD.EventSystem.update()中吐出以下错误:

The song loads and plays fine... until it hits that 500ms syncpoint I added. At this point, VC# spits out the following error from within FMOD.EventSystem.update():


回调是在垃圾收集类型为
'Game!FMOD.CHANNEL_CALLBACK :: Invoke'的委托。这可能会导致应用程序崩溃,损坏和
数据丢失。将代理传递给非托管代码时,它们必须由
托管应用程序保持活动状态,直到它保证它们永远不会被调用。

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.



因此莫名其妙地失去了我通过它的委托的轨道。持有该委托的音乐实例尚未被垃圾收集 - 我现在将它存储在一个静态变量中 - 但我尝试过使用静态方法也无济于事。如果我禁用CallbackOnCollectedDelegate MDA,则该错误将成为一个空引用异常,所以MDA没有错误。

So somehow FMOD is losing track of the delegate I passed it. The Music instance that holds the delegate has not been garbage collected - I'm storing it in a static variable for now - but I've tried with a static method too to no avail. If I disable the CallbackOnCollectedDelegate MDA the error becomes a null reference exception, so the MDA isn't mistaken. I assume I must just not fully understand what FMOD is doing here.

任何C#+ FMOD大师都能看到我的错误吗?

Are any C# + FMOD gurus able to see my mistake?

推荐答案

    channel.setCallback(channelCallback);

这是问题陈述。 FMod是非托管代码。您正在创建委托对象并将其传递给非托管代码。问题是,垃圾收集器不能跟踪本机代码所持有的引用。接下来的垃圾回收会找到 no 引用该对象并收集它。 Kaboom在本机代码进行回调时。

That's the problem statement. FMod is unmanaged code. You are creating a delegate object here and passing it to the unmanaged code. Problem is, the garbage collector cannot track references held by native code. The next garbage collection will find no references to the object and collect it. Kaboom when the native code makes the callback.

您需要自己保留一个引用,以免发生这种情况:

You need to keep a reference yourself so this won't happen:

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包装代码中找到实际的委托类型,我仅仅猜到SomeDelegateType。

You need to find the actual delegate type from the FMod wrapper code, I merely guessed at "SomeDelegateType".

这篇关于回收代表正在收集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆