最近在看ET的服务端(5.0版本)框架,突然发现了一点一直搞不太懂。是关于ActorLocationSender组件的。这个类管理一个待发送消息的队列,还有一个ETTaskCompletionSource对象用于获取异步方法的值。该类在初始化后,会遍历队列中的元素,执行发送任务。
public static async ETVoid UpdateAsync(this ActorLocationSender self)
{
try
{
.......
while (true)
{
// 从队列中获取对头元素,或者创建一个
ActorTask actorTask = await self.GetAsync();
....
// 异步等待消送和返回
await self.RunTask(actorTask);
.....
}
}
catch (Exception e)
{
Log.Error(e);
}
}
private static ETTask<ActorTask> GetAsync(this ActorLocationSender self)
{
if (self.WaitingTasks.Count > 0) // 队列中有,则直接获取
{
ActorTask task = self.WaitingTasks.Peek();
return ETTask.FromResult(task);
}
// 队列中没有,则直接创建一个ETTaskCompletionSource对象,返回Task属性
self.Tcs = new ETTaskCompletionSource<ActorTask>();
return self.Tcs.Task;
}
private static void AllowGet(this ActorLocationSender self)
{
// 队列中没有元素或者Tcs为空,直接返回
...
ActorTask task = self.WaitingTasks.Peek();
var t = self.Tcs;
self.Tcs = null;
// 设置回调,ActorLocationSender中的任务结束
t.SetResult(task);
}
在RunTask方法中,等待ActorTask中发送的消息返回,如果该消息没有异常,则会直接设置ActorTask.Tcs回调,结束当前的ActorTask任务。此时ActorLocationSender的任务队列不为空的时候,会继续通过GetAsync方法获取队列中的元素。直到队列为空,则会直接返回ActorLocationSender.Tcs对象,这时候应该是会发送一个空消息,会抛出错误(猜测会抛出ErrorCode.ERR_NotFoundActor)。如果某一次发送消息,触发了ERR_NotFoundActor错误码,在5次以内会调用到AllowGet方法,会将对头元素直接设置回调,结束当前的ActorLocationSender.Tcs任务。然后接着循环。
疑问的地方在于:1、没看到明显的跳出while循环的地方,除了在等待的过程中instanceId变化了;2、在触发了ERR_NotFoundActor错误码后,其实已经结束了当前的ActorLocationSender.Tcs任务了,后面再进循环,到底是进行的啥任务?;3、UpdateAsync方法,是等待的ActorLocationSender.Tcs任务吗?;4、所有的ActorTask的任务都结束后,再结束ActorLocationSender.Tcs任务吗?