using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEngine;
public struct DelayedQueueItem
{
public float time;
public Action action;
}
public class Loom : MonoBehaviour
{
///
/// 最大线程数量
///
public static int maxThreads = 8;
///
/// 线程数量
///
static int numThreads;
private static Loom _currentLoom;
public static Loom CurrentLoom
{
get
{
Initialize();
return _currentLoom;
}
}
///
/// 是否已经初始化
///
static bool initialized;
///
/// 作为初始化方法自己调用,可在初始化场景调用一次即可
///
public static void Initialize()
{
if (!initialized)
{
if (!Application.isPlaying)
return;
initialized = true;
GameObject g = new GameObject("Loom");
//####永不销毁
DontDestroyOnLoad(g);
_currentLoom = g.AddComponent();
}
}
///
/// 延迟执行的队列
///
private List _delayedQueueItems = new List();
///
/// 目前正在延迟执行的队列
///
private List _currentDelayedQueueItems = new List();
///
/// 新添加的ACTION
///
private List _newActions = new List();
///
/// 不延迟执行
///
private List _CurrentNoDelayActions = new List();
public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
///
/// 添加到主线程执行
///
///
///
public static void QueueOnMainThread(Action action, float delayTime)
{
if (delayTime != 0)
{
if (CurrentLoom != null)
{
lock (CurrentLoom._delayedQueueItems)
{
CurrentLoom._delayedQueueItems.Add(new DelayedQueueItem { time = Time.time + delayTime, action = action });
}
}
}
else
{
if (CurrentLoom != null)
{
lock (CurrentLoom._newActions)
{
CurrentLoom._newActions.Add(action);
}
}
}
}
public static Thread RunAsync(Action action)
{
Initialize();
while (numThreads >= maxThreads)
{
//将当前线程挂起指定的毫秒数。
Thread.Sleep(1);
}
//递增线程数量(Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果)
Interlocked.Increment(ref numThreads);
//将方法排入队列以便执行。 此方法在有线程池线程变得可用时执行
ThreadPool.QueueUserWorkItem(RunAction, action);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
}
finally
{
//递减线程数量(Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果)
Interlocked.Decrement(ref numThreads);
}
}
void Update()
{
lock (_newActions)
{
_CurrentNoDelayActions.Clear();
_CurrentNoDelayActions.AddRange(_newActions);
_newActions.Clear();
}
foreach (var actionItem in _CurrentNoDelayActions)
{
actionItem();
}
lock (_delayedQueueItems)
{
_currentDelayedQueueItems.Clear();
_currentDelayedQueueItems.AddRange(_delayedQueueItems.Where(d => d.time <= Time.time));
foreach (var item in _currentDelayedQueueItems)
{
_delayedQueueItems.Remove(item);
}
}
foreach (var delayed in _currentDelayedQueueItems)
{
delayed.action();
}
}
void OnDisable()
{
if (_currentLoom == this)
{
_currentLoom = null;
}
}
}