XLua框架,Unity3D,WEBGL,报错ArgumentException-Destination-array-was-not-long-enough
Unity使用XLua框架,打WEBGL包,运行时报错:ArgumentException: Destination array was not long enough 具体的错误如下: dangerArgumentException: Destination array was not long enough. Check destIndex and length, and the array's lower bounds {: .prompt-danger } 由于我们UI使用的时FGUI,所以这个错误的具体表现是: 错误表现 在编辑器中运行良好,没有任何问题 打包成WEBGL运行就报这个错,但不是每次都报错, 如果报错,那么UI逻辑是正常的,如果不报错,那么UI逻辑异常,比如按钮的绑定事件错乱 解决办法 我在XLua的Issue中,找到了大佬的解决办法。是XLua在释放资源时的Lock操作引起的。原issue地址。但是大佬的贴的代码,不能直接运行,需要稍加修改才行【大佬可能给的时伪代码】。我在这里把解决步骤归纳一下: 1.添加一个非锁互斥队列【也可以不用添加,就用系统的也行】: using System.Threading; namespace XLua { public class LockFreeQueue<T> { internal class SingleLinkNode<U> where U : T { public SingleLinkNode<U> Next; public U Item; } static private bool CAS<T>(ref T location, T comparand, T newValue) where T : class { return comparand == Interlocked.CompareExchange(ref location, newValue, comparand); } SingleLinkNode<T> head; SingleLinkNode<T> tail; int count; public int Count { get { return count; } } public bool IsEmpty { get { return count <= 0; } } public LockFreeQueue() { head = new SingleLinkNode<T>(); tail = head; count = 0; } public void Enqueue(T item) { SingleLinkNode<T> oldTail = null; SingleLinkNode<T> oldTailNext; SingleLinkNode<T> newNode = new SingleLinkNode<T>(); newNode.Item = item; bool newNodeAdded = false; while (!newNodeAdded) { oldTail = tail; oldTailNext = oldTail.Next; if (tail == oldTail) { if (oldTailNext == null) newNodeAdded = CAS<SingleLinkNode<T>>(ref tail.Next, null, newNode); else CAS<SingleLinkNode<T>>(ref tail, oldTail, oldTailNext); } } CAS<SingleLinkNode<T>>(ref tail, oldTail, newNode); Interlocked.Increment(ref count); } public bool TryDequeue(out T item) { item = default(T); SingleLinkNode<T> oldHead = null; bool haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = head; SingleLinkNode<T> oldTail = tail; SingleLinkNode<T> oldHeadNext = oldHead.Next; if (oldHead == head) { if (oldHead == oldTail) { if (oldHeadNext == null) { return false; } CAS<SingleLinkNode<T>>(ref tail, oldTail, oldHeadNext); } else { item = oldHeadNext.Item; haveAdvancedHead = CAS<SingleLinkNode<T>>(ref head, oldHead, oldHeadNext); } } } Interlocked.Decrement(ref count); return true; } public T Dequeue() { T result; if (TryDequeue(out result)) return result; return default(T); } public void Clear() { while (Count > 0) { Dequeue(); } } } } 2.修改XLua源码,添加条件编译,让WEBGL在释放引用的时候不加锁 改下面几个地方: ...