LuaInterface / C# - 使用.NET对象创建的闭包永远不会被清除

时间:2013-02-02 20:15:24

标签: c# function lua closures luainterface

我在C#应用程序中使用最新版本的LuaInterface(http://code.google.com/p/luainterface/)。我遇到了一个问题,即Lua类无法清除ObjectTranslator'对象'和'objectsBackMap'字典中的内部引用,导致内存使用量不断增长。

以下代码说明了问题:

public class Program
{
    public static void Main()
    {
        Lua lua = new Lua();
        string f = @"
            return function(myClass, dotNetObject)
              local f = function() dotNetObject:TestMethod() end
              myClass:StoreFunction(f);
            end";


        var result = lua.DoString(f)[0] as LuaFunction;

        MyClass testItem = new MyClass();

        for (int i = 0; i < 50; i++)
        {
            DotNetObject o = new DotNetObject();
            result.Call(testItem, o);
        }


        lua.DoString("collectgarbage()");
        ObjectTranslator translator = (ObjectTranslator)typeof(Lua).GetField("translator", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(lua);
        Console.WriteLine("Object count: " + translator.objects.Count);
        //Prints out 51. 50 of these items are instances of 'DotNetObject', despite them being unreachable.
        //Forcing a .NET garbage collection does not help. They are still being held onto by the object translator.
    }

    public class MyClass
    {
        public void StoreFunction(LuaFunction function)
        {
            //I would normally save off the function here to be executed later
        }
    }

    public class DotNetObject
    {
        public void TestMethod()
        {
        }
    }
}

当匿名函数(local f = ...)从外部作用域创建涉及.NET对象的闭包时,就会出现问题。只要Lua解释器保持活动状态,我创建的50个DotNetObject类实例将永远不会被垃圾收集,即使在Lua中强制执行GC时也是如此。

在MyClass.StoreFunction中手动处理LuaFunction(function.Dispose())对象解决了这个问题,但这是不可取的,因为在我的实际应用程序中我不知道函数何时执行 - 或者它是否曾经将。强迫我处理LuaFunction改变了应用程序的整个架构,这样我基本上通过处理包含LuaFunction的对象和包含该对象的对象来进行手动内存管理,一直到链。

那么,这是LuaInterface中的错误,还是我错误地使用了库?非常感谢任何建议,谢谢!

0 个答案:

没有答案