Files
plugin-library/Assets/Main/HotfixUpdateScript/Runtime/HotUpdate/ComponentExtensions.cs

162 lines
5.1 KiB
C#
Raw Normal View History

2025-09-02 14:15:18 +08:00
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks;
using Rokid.UXR;
using Stary.Evo;
namespace Main
{
public class CancellationTokenCore : MonoBehaviour
{
#region Instance
private static CancellationTokenCore m_Instance;
/// <summary>
/// Singleton Object
/// </summary>
public static CancellationTokenCore Instance
{
get
{
if (m_Instance == null)
{
CancellationTokenCore[] ts = GameObject.FindObjectsOfType<CancellationTokenCore>();
if (ts != null && ts.Length > 0)
{
if (ts.Length == 1)
{
m_Instance = ts[0];
}
else
{
throw new Exception(string.Format(
"## Uni Exception ## Cls:{0} Info:Singleton not allows more than one instance",
typeof(CancellationTokenCore)));
}
}
else
{
m_Instance =
new GameObject(string.Format("{0}(Singleton)", typeof(CancellationTokenCore).ToString()))
.AddComponent<CancellationTokenCore>();
}
}
return m_Instance;
}
}
#endregion
// 存储 CancellationTokenSource 实例的字典
private readonly Dictionary<object, CancellationTokenSource> _cancellationTokenSources =
new Dictionary<object, CancellationTokenSource>();
/// <summary>
/// 获取一个 CancellationTokenSource 实例,如果不存在则创建一个
/// </summary>
/// <param name="key">用于标识 CancellationTokenSource 的键</param>
/// <returns>CancellationTokenSource 实例</returns>
public CancellationToken CancellationTokenSource(string key)
{
if (_cancellationTokenSources.TryGetValue(key, out var cts))
{
CancelCancellationTokenSource(key);
}
cts = new CancellationTokenSource();
_cancellationTokenSources[key] = cts;
return cts.Token;
}
/// <summary>
/// 取消指定键对应的 CancellationTokenSource 实例
/// </summary>
/// <param name="key">用于标识 CancellationTokenSource 的键</param>
public void CancelCancellationTokenSource(string key)
{
if (_cancellationTokenSources.TryGetValue(key, out var cts))
{
try
{
cts.Cancel();
cts.Dispose();
}
catch (OperationCanceledException)
{
Debug.Log($"ComponentExtensions:【{key}】异步任务被取消");
}
_cancellationTokenSources.Remove(key);
}
}
/// <summary>
/// 取消所有的 CancellationTokenSource 实例
/// </summary>
public void CancelAllCancellationTokenSources()
{
foreach (var cts in _cancellationTokenSources.Values)
{
try
{
cts.Cancel();
cts.Dispose();
}
catch (OperationCanceledException)
{
Debug.Log($"ComponentExtensions:全部异步任务被取消");
}
}
_cancellationTokenSources.Clear();
}
private void OnDestroy()
{
// 在对象销毁时取消所有的 CancellationTokenSource 实例
CancelAllCancellationTokenSources();
}
}
public static class ComponentExtensions
{
/// <summary>
/// 获取组件的CancellationTokenSource当组件销毁时会取消该CancellationTokenSource
/// </summary>
/// <param name="component"></param>
/// <returns></returns>
private static CancellationToken CancellationTokenOnDestroy(this GameObject component)
{
var cts = new CancellationTokenSource();
component.GetOrAddComponent<DestroyNotifier>()
.OnDestroyEvent += () =>
{
try
{
cts.Cancel();
cts.Dispose();
}
catch (OperationCanceledException)
{
Debug.Log($"ComponentExtensions:【{component.name}】异步任务被取消");
}
};
return cts.Token;
}
class DestroyNotifier : MonoBehaviour
{
public event System.Action OnDestroyEvent;
private void OnDestroy()
{
OnDestroyEvent?.Invoke();
}
}
}
}