using XGame.Framework.Asyncs; using System.Collections.Generic; namespace XGame.Framework.Asset { /// /// 加载任务的异步操作池 /// internal sealed class AssetAsyncPool { /// /// 未使用的Agents /// Stack FreeAgents { set; get; } /// /// 使用中的Agents /// //LinkedList WorkingAgents { set; get; } Dictionary WorkingAgents { set; get; } /// /// 等待处理的Async /// LinkedList WaitingAsyncs { set; get; } /// /// 存储所有未完成的Async,方便查找 /// Dictionary AssetAsyncMap { set; get; } /// /// 是否被暂停。 /// public bool Paused { set; get; } /// /// agent的数量上限 /// public int AgentLimit { set; get; } /// /// 构造函数。 /// public AssetAsyncPool() { FreeAgents = new Stack(); WorkingAgents = new Dictionary(); WaitingAsyncs = new LinkedList(); AssetAsyncMap = new Dictionary(); Paused = false; AgentLimit = 0; } /// /// 获取代理总数量。 /// 包括使用中和未使用的代理,不一定等于AgentLimit /// public int TotalAgentCount => (FreeAgentCount + WorkingAgentCount); /// /// 获取可用代理数量。 /// 仅返回缓存池中未使用的代理数量 /// public int FreeAgentCount => FreeAgents.Count; /// /// 获取工作中代理数量。 /// public int WorkingAgentCount => WorkingAgents.Count; /// /// 获取等待Async数量。 /// public int WaitingAsyncCount => WaitingAsyncs.Count; /// /// 获取未完成的Async /// /// /// public IAssetAsync GetAssetAsync(string addressableName) { AssetAsyncMap.TryGetValue(addressableName, out IAssetAsync assetAsync); return assetAsync; } /// /// 是否包含指定的Async /// /// /// public bool ContainsAssetAsync(string addressableName) { return AssetAsyncMap.ContainsKey(addressableName); } /// /// 获取未使用的Agent /// 可能从缓存里取,也可能是新建的Agent /// /// private IAssetAsyncAgent GetFreeAgent() { if (FreeAgents.Count > 0) { return FreeAgents.Pop(); } if (TotalAgentCount < AgentLimit) { var agent = new AssetAsyncAgent(); return agent; } return null; } /// /// 增加AssetAsync。 /// /// public void AddAsync(IAssetAsync assetAsync) { if (AssetAsyncMap.ContainsKey(assetAsync.AddressableName)) { //AssetsLog.Debug("Asset Add Async Repeat. Name:{0}", assetAsync.AddressableName); return; } AssetAsyncMap.Add(assetAsync.AddressableName, assetAsync); LinkedListNode current = WaitingAsyncs.Last; if (current != null) { WaitingAsyncs.AddAfter(current, assetAsync); } else { WaitingAsyncs.AddFirst(assetAsync); } ProcessWaitingAsync(); } ///// ///// 移除任务。 ///// ///// 要移除任务的序列编号。 ///// 被移除的任务。 //public bool RemoveAsync(int serialId) //{ // foreach (IAssetAsync waitingAsync in WaitingAsyncs) // { // if (waitingAsync.SerialId == serialId) // { // WaitingAsyncs.Remove(waitingAsync); // return true; // } // } // foreach (IAssetAsyncAgent workingAgent in WorkingAgents) // { // if (workingAgent.Task.SerialId == serialId) // { // workingAgent.Stop(); // m_FreeAgents.Push(workingAgent); // WorkingAgents.Remove(workingAgent); // return true; // } // } // return false; //} private void ProcessWaitingAsync() { LinkedListNode current = WaitingAsyncs.First; IAssetAsyncAgent agent; while (current != null && (agent = GetFreeAgent()) != null) { LinkedListNode next = current.Next; AgentStatus status = agent.Start(current.Value); if (status == AgentStatus.CanResume) {//设置监听 current.Value.On(OnAsyncCompleted); WorkingAgents.Add(current.Value, agent); } else { agent.Stop(); FreeAgents.Push(agent); if (status == AgentStatus.Done || status == AgentStatus.UnknownError) { AssetAsyncMap.Remove(current.Value.AddressableName); } } if (status != AgentStatus.HasToWait) { WaitingAsyncs.Remove(current); } current = next; } } void OnAsyncCompleted(IAsync aAsync) { IAssetAsync assetAsync = aAsync as IAssetAsync; if (assetAsync != null) { if (WorkingAgents.TryGetValue(assetAsync, out IAssetAsyncAgent agent)) { agent.Stop(); WorkingAgents.Remove(assetAsync); FreeAgents.Push(agent); } AssetAsyncMap.Remove(assetAsync.AddressableName); } ProcessWaitingAsync(); } /// /// 移除所有任务。 /// public void Clear() { WaitingAsyncs.Clear(); AssetAsyncMap.Clear(); foreach (var it in WorkingAgents) { it.Value.Stop(); FreeAgents.Push(it.Value); } WorkingAgents.Clear(); } public void Dispose() { WaitingAsyncs.Clear(); while (FreeAgentCount > 0) { FreeAgents.Pop().Dispose(); } foreach (var it in WorkingAgents) { it.Value.Dispose(); } WorkingAgents.Clear(); AssetAsyncMap.Clear(); } } }