我在 C# 应用程序中使用最新版本的 LuaInterface ( http://code.google.com/p/luainterface/ )。我遇到了一个问题,即 Lua 类无法清理 ObjectTranslator 'objects' 和 '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()
{
}
}
}
当匿名函数(本地 f = ...)从外部范围创建涉及 .NET 对象的闭包时,就会出现问题。只要 Lua 解释器还活着,我创建的 50 个 DotNetObject 类实例就永远不会被垃圾回收,即使在 Lua 中强制进行 GC 时也是如此。
在 MyClass.StoreFunction 中手动处理 LuaFunction (function.Dispose()) 对象可以解决问题,但这是不可取的,因为在我的实际应用程序中,我不知道函数何时会执行——或者它是否会执行。强迫我处置 LuaFunction 会改变应用程序的整个架构,因此我基本上是通过处置包含 LuaFunction 的对象以及包含该对象的对象,一直沿链向上进行手动内存管理。
那么,这是 LuaInterface 中的一个错误,还是我错误地使用了该库?非常感谢任何建议,谢谢!