在CoroutineLockQueue.cs代码中。
// 返回值,是否找到了一个有效的协程锁
public static bool Notify(this CoroutineLockQueue self, int level)
{
// 有可能WaitCoroutineLock已经超时抛出异常,所以要找到一个未处理的WaitCoroutineLock
while (self.queue.Count > 0)
{
WaitCoroutineLock waitCoroutineLock = self.queue.Dequeue();
if (waitCoroutineLock.IsDisposed())
{
continue;
}
CoroutineLock coroutineLock = self.AddChild<CoroutineLock, int, long, int>(self.type, self.Id, level, true);
waitCoroutineLock.SetResult(coroutineLock);
return true;
}
if (self.CurrentCoroutineLock is not null)
{
Log.Info("!!!!!!!!!!!");
return true;
}
return false;
}
是没有 self.CurrentCoroutineLock is not null
的判断的。这可能会导致一些时候第一个锁被意外销毁。
在ET的设计中,应该是不会存在这个情况的。
我也不知道是不是我写的有问题,但可以通过简单的方式复现该问题。
在ET的Demo当中,修改UILoginComponentSystem。添加以下代码。UILoginComponent添加对应的IUpdate事件bool isFirst
属性
[EntitySystem]
private static void Update(this ET.Client.UILoginComponent self)
{
if (Input.GetKeyDown(KeyCode.Space))
{
self.isFirst = true;
}
if (Input.GetKey(KeyCode.Space))
{
self.Test().Coroutine();
}
}
const int testKey = 10;
const long testHash = 1000;
static async ETTask Test(this ET.Client.UILoginComponent self)
{
var wait = self.Root().GetComponent<TimerComponent>();
if (self.isFirst)
{
self.isFirst = false;
await wait.WaitAsync(100);
self.test_1().Coroutine();
}
else
{
self.test_2().Coroutine();
await wait.WaitAsync(Random.Range(200, 400));
self.test_2().Coroutine();
}
}
static async ETTask test_1(this ET.Client.UILoginComponent self)
{
var coroutineLock = self.Root().GetComponent<CoroutineLockComponent>();
var wait = self.Root().GetComponent<TimerComponent>();
using (await coroutineLock.Wait(testKey, testHash))
{
//模拟一次等待
await wait.WaitAsync(1000);
}
}
static async ETTask test_2(this ET.Client.UILoginComponent self)
{
var coroutineLock = self.Root().GetComponent<CoroutineLockComponent>();
using (await coroutineLock.Wait(testKey, testHash))
{
//模拟一次等待
Log.Info("test_2 finish");
}
}
在登录界面按住空格,就可以看到 !!!!!!!!!!!
的输出。
该现象导致了我们加协程锁保护频繁异步开关相同界面时,顺序出错导致界面没有被正确关闭的问题。