com.alicizax.unity.tuyoogam.../Runtime/OperationSystem/AsyncOperationBase.cs

260 lines
6.7 KiB
C#
Raw Normal View History

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