Files
plugin-library/Assets/Main/HotfixUpdateScript/Runtime/HotUpdate/ComponentExtensions.cs
2025-09-02 14:15:18 +08:00

162 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}
}