using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; namespace YooAsset { public abstract class AsyncOperationBase : IEnumerator, IComparable { private readonly List _childs = new List(10); private Action _callback; private string _packageName = null; private int _whileFrame = 1000; /// /// 等待异步执行完成 /// internal bool IsWaitForAsyncComplete { private set; get; } = false; /// /// 是否已经完成 /// internal bool IsFinish { private set; get; } = false; /// /// 优先级 /// public uint Priority { set; get; } = 0; /// /// 状态 /// public EOperationStatus Status { get; protected set; } = EOperationStatus.None; /// /// 错误信息 /// public string Error { get; protected set; } /// /// 处理进度 /// public float Progress { get; protected set; } /// /// 所属包裹名称 /// public string PackageName { get { return _packageName; } } /// /// 是否已经完成 /// public bool IsDone { get { return Status == EOperationStatus.Failed || Status == EOperationStatus.Succeed; } } /// /// 完成事件 /// public event Action Completed { add { if (IsDone) value.Invoke(this); else _callback += value; } remove { _callback -= value; } } /// /// 异步操作任务 /// public Task Task { get { if (_taskCompletionSource == null) { _taskCompletionSource = new TaskCompletionSource(); if (IsDone) _taskCompletionSource.SetResult(null); } return _taskCompletionSource.Task; } } internal abstract void InternalStart(); internal abstract void InternalUpdate(); internal virtual void InternalAbort() { } internal virtual void InternalWaitForAsyncComplete() { throw new System.NotImplementedException(this.GetType().Name); } /// /// 设置包裹名称 /// internal void SetPackageName(string packageName) { _packageName = packageName; } /// /// 添加子任务 /// internal void AddChildOperation(AsyncOperationBase child) { #if UNITY_EDITOR if (_childs.Contains(child)) throw new Exception($"The child node {child.GetType().Name} already exists !"); #endif _childs.Add(child); } /// /// 开始异步操作 /// internal void StartOperation() { if (Status == EOperationStatus.None) { Status = EOperationStatus.Processing; InternalStart(); } } /// /// 更新异步操作 /// internal void UpdateOperation() { if (IsDone == false) InternalUpdate(); if (IsDone && IsFinish == false) { IsFinish = true; // 进度百分百完成 Progress = 1f; //注意:如果完成回调内发生异常,会导致Task无限期等待 _callback?.Invoke(this); if (_taskCompletionSource != null) _taskCompletionSource.TrySetResult(null); } } /// /// 终止异步任务 /// internal void AbortOperation() { foreach (var child in _childs) { child.AbortOperation(); } if (IsDone == false) { Status = EOperationStatus.Failed; Error = "user abort"; YooLogger.Warning($"Async operaiton {this.GetType().Name} has been abort !"); InternalAbort(); } } /// /// 执行While循环 /// protected bool ExecuteWhileDone() { if (IsDone == false) { // 执行更新逻辑 InternalUpdate(); // 当执行次数用完时 _whileFrame--; if (_whileFrame <= 0) { Status = EOperationStatus.Failed; Error = $"Operation {this.GetType().Name} failed to wait for async complete !"; YooLogger.Error(Error); } } return IsDone; } /// /// 清空完成回调 /// protected void ClearCompletedCallback() { _callback = null; } /// /// 等待异步执行完毕 /// public void WaitForAsyncComplete() { if (IsDone) return; //TODO 防止异步操作被挂起陷入无限死循环! // 例如:文件解压任务或者文件导入任务! if (Status == EOperationStatus.None) { StartOperation(); } IsWaitForAsyncComplete = true; InternalWaitForAsyncComplete(); } #region 调试信息 #endregion #region 排序接口实现 public int CompareTo(AsyncOperationBase other) { return other.Priority.CompareTo(this.Priority); } #endregion #region 异步编程相关 bool IEnumerator.MoveNext() { return !IsDone; } void IEnumerator.Reset() { } object IEnumerator.Current => null; private TaskCompletionSource _taskCompletionSource; #endregion } }