diff --git a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs
index 64d59e86..cb621a75 100644
--- a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs
+++ b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs
@@ -228,7 +228,18 @@ namespace YooAsset
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)
@@ -353,7 +364,6 @@ namespace YooAsset
public void WaitForAsyncComplete()
{
//TODO 防止异步操作被挂起陷入无限死循环!
- // 例如:文件解压任务或者文件导入任务!
if (Status == EOperationStatus.None)
{
StartOperation();
diff --git a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
index 876c4aba..e72de0df 100644
--- a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
+++ b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
@@ -5,7 +5,7 @@ using System.Diagnostics;
namespace YooAsset
{
- internal class OperationSystem
+ internal static class OperationSystem
{
#if UNITY_EDITOR
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
@@ -57,11 +57,14 @@ namespace YooAsset
///
public static void Initialize()
{
- _isInitialize = true;
- _watch = Stopwatch.StartNew();
+ if (_isInitialize == false)
+ {
+ _isInitialize = true;
+ _watch = Stopwatch.StartNew();
- // 创建全局调度器
- CreatePackageScheduler(GLOBAL_SCHEDULER_NAME, 0);
+ // 创建全局调度器
+ CreatePackageScheduler(GLOBAL_SCHEDULER_NAME, int.MaxValue);
+ }
}
///
@@ -97,6 +100,7 @@ namespace YooAsset
///
public static void DestroyAll()
{
+ _isInitialize = false;
YooLogger.Log("Operation system destroy all !");
// 清空所有调度器
@@ -108,7 +112,6 @@ namespace YooAsset
_schedulerList.Clear();
_schedulerListDirty = false;
_createIndex = 0;
- _isInitialize = false;
_watch = null;
_frameTime = 0;
@@ -120,6 +123,8 @@ namespace YooAsset
///
public static void CreatePackageScheduler(string packageName, int priority)
{
+ DebugCheckInitialize(packageName);
+
if (_schedulerDic.ContainsKey(packageName))
{
throw new YooInternalException($"Package scheduler already exists: {packageName}");
@@ -136,6 +141,8 @@ namespace YooAsset
///
public static void DestroyPackageScheduler(string packageName)
{
+ DebugCheckInitialize(packageName);
+
// 不允许销毁默认调度器
if (packageName == GLOBAL_SCHEDULER_NAME)
{
@@ -155,6 +162,8 @@ namespace YooAsset
///
public static void ClearPackageOperation(string packageName)
{
+ DebugCheckInitialize(packageName);
+
var scheduler = GetScheduler(packageName);
scheduler.ClearAll();
}
@@ -164,6 +173,8 @@ namespace YooAsset
///
public static void StartOperation(string packageName, AsyncOperationBase operation)
{
+ DebugCheckInitialize(packageName);
+
var scheduler = GetScheduler(packageName);
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 调试信息
internal static List GetDebugOperationInfos(string packageName)
{
+ DebugCheckInitialize(packageName);
+
var scheduler = GetScheduler(packageName);
return scheduler.GetDebugOperationInfos();
}
#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
}
}
diff --git a/Assets/YooAsset/Runtime/OperationSystem/README.md b/Assets/YooAsset/Runtime/OperationSystem/README.md
index 128659b4..5cd39d31 100644
--- a/Assets/YooAsset/Runtime/OperationSystem/README.md
+++ b/Assets/YooAsset/Runtime/OperationSystem/README.md
@@ -227,16 +227,16 @@ public static void StartOperation(string packageName, AsyncOperationBase operati
#### 回调监听
-```csharp
-///
-/// 注册任务开始回调
-///
-public static void RegisterStartCallback(Action callback);
+OperationSystem **当前未提供**全局任务开始/结束回调的注册接口。
-///
-/// 注册任务结束回调
-///
-public static void RegisterFinishCallback(Action callback);
+如需监听任务结束(推荐),请直接订阅具体任务的 `Completed` 事件:
+
+```csharp
+var operation = package.LoadAssetAsync(location);
+operation.Completed += op =>
+{
+ // TODO : 根据 op.Status 判断成功/失败
+};
```
---
@@ -515,4 +515,4 @@ IEnumerator + IComparable
4. **子任务中止**:父操作中止时会自动中止所有子操作
5. **回调异常**:`Completed` 回调中的异常会被捕获并记录,不会中断系统
6. **编辑器重置**:编辑器中使用 `RuntimeInitializeOnLoadMethod` 自动重置状态
-7. **循环保护**:在 `InternalWaitForAsyncComplete()` 中如果使用 `ExecuteWhileDone()`,内部默认有 1000 次执行保护,防止无限循环
+7. **循环保护**:在 `InternalWaitForAsyncComplete()` 中建议使用 `RunBatchExecution()`(默认 1000 次)限制单次推进次数,避免陷入无限循环或长时间占用主线程