refactor : 重构异步操作模块

This commit is contained in:
何冠峰
2026-01-13 11:23:50 +08:00
parent 7198e639d9
commit b796b1a44e
3 changed files with 54 additions and 19 deletions

View File

@@ -228,7 +228,18 @@ namespace YooAsset
DebugUpdateRecording(); DebugUpdateRecording();
// 更新任务 // 更新任务
InternalUpdate(); // 注意:兜底隔离机制
// 说明检测的异常源包含I/O解压/读写权限/磁盘满),平台差异等
try
{
InternalUpdate();
}
catch (Exception ex)
{
Status = EOperationStatus.Failed;
Error = ex.ToString();
YooLogger.Error($"Exception in {this.GetType().Name}.InternalUpdate : {ex}");
}
} }
if (IsDone && IsFinish == false) if (IsDone && IsFinish == false)
@@ -353,7 +364,6 @@ namespace YooAsset
public void WaitForAsyncComplete() public void WaitForAsyncComplete()
{ {
//TODO 防止异步操作被挂起陷入无限死循环! //TODO 防止异步操作被挂起陷入无限死循环!
// 例如:文件解压任务或者文件导入任务!
if (Status == EOperationStatus.None) if (Status == EOperationStatus.None)
{ {
StartOperation(); StartOperation();

View File

@@ -5,7 +5,7 @@ using System.Diagnostics;
namespace YooAsset namespace YooAsset
{ {
internal class OperationSystem internal static class OperationSystem
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)] [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
@@ -57,11 +57,14 @@ namespace YooAsset
/// </summary> /// </summary>
public static void Initialize() public static void Initialize()
{ {
_isInitialize = true; if (_isInitialize == false)
_watch = Stopwatch.StartNew(); {
_isInitialize = true;
_watch = Stopwatch.StartNew();
// 创建全局调度器 // 创建全局调度器
CreatePackageScheduler(GLOBAL_SCHEDULER_NAME, 0); CreatePackageScheduler(GLOBAL_SCHEDULER_NAME, int.MaxValue);
}
} }
/// <summary> /// <summary>
@@ -97,6 +100,7 @@ namespace YooAsset
/// </summary> /// </summary>
public static void DestroyAll() public static void DestroyAll()
{ {
_isInitialize = false;
YooLogger.Log("Operation system destroy all !"); YooLogger.Log("Operation system destroy all !");
// 清空所有调度器 // 清空所有调度器
@@ -108,7 +112,6 @@ namespace YooAsset
_schedulerList.Clear(); _schedulerList.Clear();
_schedulerListDirty = false; _schedulerListDirty = false;
_createIndex = 0; _createIndex = 0;
_isInitialize = false;
_watch = null; _watch = null;
_frameTime = 0; _frameTime = 0;
@@ -120,6 +123,8 @@ namespace YooAsset
/// </summary> /// </summary>
public static void CreatePackageScheduler(string packageName, int priority) public static void CreatePackageScheduler(string packageName, int priority)
{ {
DebugCheckInitialize(packageName);
if (_schedulerDic.ContainsKey(packageName)) if (_schedulerDic.ContainsKey(packageName))
{ {
throw new YooInternalException($"Package scheduler already exists: {packageName}"); throw new YooInternalException($"Package scheduler already exists: {packageName}");
@@ -136,6 +141,8 @@ namespace YooAsset
/// </summary> /// </summary>
public static void DestroyPackageScheduler(string packageName) public static void DestroyPackageScheduler(string packageName)
{ {
DebugCheckInitialize(packageName);
// 不允许销毁默认调度器 // 不允许销毁默认调度器
if (packageName == GLOBAL_SCHEDULER_NAME) if (packageName == GLOBAL_SCHEDULER_NAME)
{ {
@@ -155,6 +162,8 @@ namespace YooAsset
/// </summary> /// </summary>
public static void ClearPackageOperation(string packageName) public static void ClearPackageOperation(string packageName)
{ {
DebugCheckInitialize(packageName);
var scheduler = GetScheduler(packageName); var scheduler = GetScheduler(packageName);
scheduler.ClearAll(); scheduler.ClearAll();
} }
@@ -164,6 +173,8 @@ namespace YooAsset
/// </summary> /// </summary>
public static void StartOperation(string packageName, AsyncOperationBase operation) public static void StartOperation(string packageName, AsyncOperationBase operation)
{ {
DebugCheckInitialize(packageName);
var scheduler = GetScheduler(packageName); var scheduler = GetScheduler(packageName);
scheduler.StartOperation(operation); scheduler.StartOperation(operation);
} }
@@ -179,15 +190,29 @@ namespace YooAsset
} }
// 严格模式:非默认包裹必须先创建调度器 // 严格模式:非默认包裹必须先创建调度器
throw new YooInternalException($"Operation scheduler not found: {packageName}. Please call YooAssets.CreatePackage() first!"); throw new YooInternalException($"Operation scheduler not found: {packageName}.");
} }
#region #region
internal static List<DebugOperationInfo> GetDebugOperationInfos(string packageName) internal static List<DebugOperationInfo> GetDebugOperationInfos(string packageName)
{ {
DebugCheckInitialize(packageName);
var scheduler = GetScheduler(packageName); var scheduler = GetScheduler(packageName);
return scheduler.GetDebugOperationInfos(); return scheduler.GetDebugOperationInfos();
} }
#endregion #endregion
#region
[Conditional("DEBUG")]
private static void DebugCheckInitialize(string packageName)
{
if (string.IsNullOrWhiteSpace(packageName))
throw new YooInternalException("Package name is null or empty.");
if (_isInitialize == false)
throw new YooInternalException($"{nameof(OperationSystem)} not initialized !");
}
#endregion
} }
} }

View File

@@ -227,16 +227,16 @@ public static void StartOperation(string packageName, AsyncOperationBase operati
#### 回调监听 #### 回调监听
```csharp OperationSystem **当前未提供**全局任务开始/结束回调的注册接口。
/// <summary>
/// 注册任务开始回调
/// </summary>
public static void RegisterStartCallback(Action<string, AsyncOperationBase> callback);
/// <summary> 如需监听任务结束(推荐),请直接订阅具体任务的 `Completed` 事件:
/// 注册任务结束回调
/// </summary> ```csharp
public static void RegisterFinishCallback(Action<string, AsyncOperationBase> callback); var operation = package.LoadAssetAsync<GameObject>(location);
operation.Completed += op =>
{
// TODO : 根据 op.Status 判断成功/失败
};
``` ```
--- ---
@@ -515,4 +515,4 @@ IEnumerator + IComparable<AsyncOperationBase>
4. **子任务中止**:父操作中止时会自动中止所有子操作 4. **子任务中止**:父操作中止时会自动中止所有子操作
5. **回调异常**`Completed` 回调中的异常会被捕获并记录,不会中断系统 5. **回调异常**`Completed` 回调中的异常会被捕获并记录,不会中断系统
6. **编辑器重置**:编辑器中使用 `RuntimeInitializeOnLoadMethod` 自动重置状态 6. **编辑器重置**:编辑器中使用 `RuntimeInitializeOnLoadMethod` 自动重置状态
7. **循环保护**:在 `InternalWaitForAsyncComplete()`如果使用 `ExecuteWhileDone()`,内部默认 1000 次执行保护,防止无限循环 7. **循环保护**:在 `InternalWaitForAsyncComplete()`建议使用 `RunBatchExecution()`默认 1000 次)限制单次推进次数,避免陷入无限循环或长时间占用主线程