fix: resolve UnloadAllAssetsOperation deadlock when releasing zero-ref pending providers

This commit is contained in:
何冠峰
2026-06-02 14:21:18 +08:00
parent 20ae423bbe
commit a5f4b555e7
2 changed files with 42 additions and 0 deletions

View File

@@ -25,6 +25,7 @@ namespace YooAsset
CheckOptions,
ReleaseAll,
TryAbortLoader,
RequestForceDestroy,
CheckLoading,
DestroyAll,
Done,
@@ -93,6 +94,17 @@ namespace YooAsset
{
loader.TryAbortLoader();
}
_steps = ESteps.RequestForceDestroy;
}
if (_steps == ESteps.RequestForceDestroy)
{
// 向所有资源提供者下发强制销毁请求
// 注意:防止零引用且尚未进入加载阶段的任务被无限挂起,从而导致 CheckLoading 死锁。
foreach (var provider in _resManager.ProviderDic.Values)
{
provider.RequestForceDestroy();
}
_steps = ESteps.CheckLoading;
}

View File

@@ -67,6 +67,11 @@ namespace YooAsset
/// </summary>
public bool IsDestroyed { private set; get; } = false;
/// <summary>
/// 是否已收到强制销毁请求
/// </summary>
public bool ForceDestroyRequested { private set; get; } = false;
/// <summary>
/// 加载任务是否进行中
/// </summary>
@@ -119,6 +124,18 @@ namespace YooAsset
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 注意:收到强制销毁请求时,未在加载中的任务立即结束,防止零引用任务被无限挂起导致卸载流程死锁!
if (ForceDestroyRequested)
{
if (IsLoading == false)
{
InvokeCompletion("Provider force destroyed during unload all assets !", EOperationStatus.Failed);
return;
}
// 注意:已进入加载阶段则继续等待自然完成
}
// 注意:未在加载中的任务可以挂起!
if (IsLoading == false)
{
@@ -199,11 +216,24 @@ namespace YooAsset
}
protected abstract void ProcessBundleResult();
/// <summary>
/// 请求强制销毁
/// 注意:用于卸载流程,标记后未在加载中的任务会在下一次更新时立即结束。
/// </summary>
public void RequestForceDestroy()
{
ForceDestroyRequested = true;
}
/// <summary>
/// 销毁资源提供者
/// 注意:该方法是幂等的,重复调用不会重复释放资源。
/// </summary>
public void DestroyProvider()
{
if (IsDestroyed)
return;
IsDestroyed = true;
// 检测是否为正常销毁