起因
xlua重启虚拟机时,需要调用Env.Dispose();
但会抛出异常"try to dispose a LuaEnv with C# callback!"
if (!translator.AllDelegateBridgeReleased())
{
throw new InvalidOperationException("try to dispose a LuaEnv with C# callback!");
}
这是因为C#端还持有lua的方法没有被释放,所以想要重启虚拟机必须要先把所有的C#委托清空
还需要注意
- 在同一个方法中释放了delegate的引用,但又立即调用了LuaEnv.Dispose().
- 在Lua端调用了Env.Dispose();
解决方法
UI部分的事件监听是大头,比如
self._btnMapShift.onClick:AddListener(CT.MainCityCtrl.OnBtnMapShift)
我们可以使用正则表式式 把这种监听替换成统一的方法里处理,然后在方法,把所有的监听都记录下来,需要重启时统一释放
统一处理UI的方法代码
function UIAddListenerIndirect(uiEnlement,eventType,func)
if uiEnlement[eventType] then
local callInfo = {
uiEnlement = uiEnlement,
eventType = eventType,
callBackFunc = func
}
uiEnlement[eventType]:AddListener(func)
table.insert(D.UIListenerDelegate,callInfo)
end
end
function UIRemoveListenerIndirect(uiEnlement,eventType,func)
if uiEnlement[eventType] then
uiEnlement[eventType]:RemoveListener(func)
end
end
function UIRemoveAllListener()
for k,v in pairs(D.UIListenerDelegate) do
local callInfo = v
--callInfo.uiDelegate:RemoveListener(callInfo.callBackFunc)
if callInfo.uiEnlement[callInfo.eventType] then
callInfo.uiEnlement[callInfo.eventType]:RemoveAllListeners()
callInfo.uiEnlement[callInfo.eventType]:Invoke("",0)
end
end
D.UIListenerDelegate = {}
end
此外还有两个方法查看C#端没被清空的委托 便于我们单独处理
1 xlua提供了一个lua方法(该方法位于XLua/Resources/xlua/util.lua.txt中): print_func_ref_by_csharp()
function print_func_ref_by_csharp()
local registry = debug.getregistry()
for k, v in pairs(registry) do
if type(k) == 'number' and type(v) == 'function' and registry[v] == k then
local info = debug.getinfo(v)
print(string.format('%s:%d', info.short_src, info.linedefined))
end
end
end
2 修改ObjectTranslator.cs 在注入委托时 记录Lua栈信息,在AllDelegateBridgeReleased时打印出来
Dictionary<int, WeakReference> delegate_bridges = new Dictionary<int, WeakReference>();
#if UNITY_EDITOR

最低0.47元/天 解锁文章
4198

被折叠的 条评论
为什么被折叠?



