79 lines
2.1 KiB
C#
79 lines
2.1 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace Kill.Utils
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 主线程执行器 - 确保回调在主线程执行
|
||
|
|
/// </summary>
|
||
|
|
public class MainThread : MonoBehaviour
|
||
|
|
{
|
||
|
|
private static MainThread _instance;
|
||
|
|
private static readonly Queue<Action> _actions = new Queue<Action>();
|
||
|
|
private static readonly object _lock = new object();
|
||
|
|
|
||
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||
|
|
private static void Initialize()
|
||
|
|
{
|
||
|
|
var go = new GameObject("MainThread");
|
||
|
|
_instance = go.AddComponent<MainThread>();
|
||
|
|
DontDestroyOnLoad(go);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Update()
|
||
|
|
{
|
||
|
|
lock (_lock)
|
||
|
|
{
|
||
|
|
while (_actions.Count > 0)
|
||
|
|
{
|
||
|
|
_actions.Dequeue()?.Invoke();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 在主线程执行
|
||
|
|
/// </summary>
|
||
|
|
public static void Enqueue(Action action)
|
||
|
|
{
|
||
|
|
if (action == null) return;
|
||
|
|
|
||
|
|
// 如果已经在主线程,直接执行
|
||
|
|
if (_instance != null && _instance.gameObject != null)
|
||
|
|
{
|
||
|
|
lock (_lock)
|
||
|
|
{
|
||
|
|
_actions.Enqueue(action);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// 如果调度器还没初始化,延迟执行
|
||
|
|
Debug.LogWarning("MainThread 未初始化,尝试延迟执行");
|
||
|
|
action?.Invoke();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 立即在主线程执行(如果已经在主线程)或排队
|
||
|
|
/// </summary>
|
||
|
|
public static void Run(Action action)
|
||
|
|
{
|
||
|
|
if (action == null) return;
|
||
|
|
|
||
|
|
// 检查是否在主线程
|
||
|
|
if (Time.frameCount > 0)
|
||
|
|
{
|
||
|
|
// 已经在主线程,直接执行
|
||
|
|
action();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// 不在主线程,排队
|
||
|
|
Enqueue(action);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|