最近在看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任務嗎?