using System;
|
using System.Collections.Generic;
|
using Cysharp.Threading.Tasks;
|
using UnityEngine;
|
|
/// <summary>
|
/// 异步懒加载:保证 factory 只执行一次,支持多个并发 await(每个调用者独立 TCS)
|
/// 非泛型设计,避免热更 AOT 泛型问题
|
/// </summary>
|
public class AsyncLazy
|
{
|
public delegate UniTask AsyncFactory();
|
|
private readonly AsyncFactory factory;
|
private List<UniTaskCompletionSource> waiters;
|
private bool hasCompleted;
|
private bool isRunning;
|
|
public AsyncLazy(AsyncFactory factory, string debugName = "")
|
{
|
this.factory = factory;
|
}
|
|
public UniTask Task
|
{
|
get
|
{
|
if (hasCompleted)
|
{
|
return UniTask.CompletedTask;
|
}
|
|
var tcs = new UniTaskCompletionSource();
|
if (waiters == null) waiters = new List<UniTaskCompletionSource>();
|
waiters.Add(tcs);
|
|
if (!isRunning)
|
{
|
isRunning = true;
|
Run().Forget();
|
}
|
|
return tcs.Task;
|
}
|
}
|
|
private async UniTaskVoid Run()
|
{
|
try
|
{
|
await factory();
|
hasCompleted = true;
|
if (waiters != null)
|
{
|
for (int i = 0; i < waiters.Count; i++)
|
waiters[i].TrySetResult();
|
waiters.Clear();
|
}
|
}
|
catch (Exception ex)
|
{
|
if (waiters != null)
|
{
|
for (int i = 0; i < waiters.Count; i++)
|
waiters[i].TrySetException(ex);
|
waiters.Clear();
|
}
|
}
|
}
|
|
public void Reset()
|
{
|
hasCompleted = false;
|
isRunning = false;
|
waiters = null;
|
}
|
}
|