using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; namespace YooAsset { public abstract class AsyncOperationBase : IEnumerator, IComparable { // 用户请求的回调 private Action _callback; // 是否已经完成 internal bool IsFinish = false; /// /// 所属包裹 /// public string PackageName { private set; get; } /// /// 优先级 /// 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 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 InternalOnStart(); internal abstract void InternalOnUpdate(); internal virtual void InternalOnAbort() { } internal void SetPackageName(string packageName) { PackageName = packageName; } internal void SetStart() { Status = EOperationStatus.Processing; InternalOnStart(); } internal void SetFinish() { IsFinish = true; // 进度百分百完成 Progress = 1f; //注意:如果完成回调内发生异常,会导致Task无限期等待 _callback?.Invoke(this); if (_taskCompletionSource != null) _taskCompletionSource.TrySetResult(null); } internal void SetAbort() { if (IsDone == false) { Status = EOperationStatus.Failed; Error = "user abort"; YooLogger.Warning($"Async operaiton has been abort : {this.GetType().Name}"); InternalOnAbort(); } } /// /// 清空完成回调 /// protected void ClearCompletedCallback() { _callback = null; } #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 } }