一个方便的多线程任务管理脚本


using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

namespace SoyEngine
{
  public class Loom : MonoBehaviour
  {
    public static int MaxThreads = Environment.ProcessorCount + 1;
    private readonly Queue<Action> _taskQueue = new Queue<Action>();
    private readonly List<Action> _actions = new List<Action>();
    private readonly List<Action> _currentActions = new List<Action>();
    private readonly List<Loom.DelayedQueueItem> _currentDelayed = new List<Loom.DelayedQueueItem>();
    private readonly List<Loom.DelayedQueueItem> _delayed = new List<Loom.DelayedQueueItem>();
    private static int _numThreads;
    private static Loom _current;
    private static bool _initialized;

    private static Loom Current
    {
      get
      {
        Loom.Initialize();
        return Loom._current;
      }
    }

    public static void Init()
    {
      Loom.Initialize();
    }

    private void Awake()
    {
      Loom._current = this;
      Loom._initialized = true;
    }

    private static void Initialize()
    {
      if (Loom._initialized || !Application.isPlaying)
        return;
      Loom._initialized = true;
      GameObject gameObject = new GameObject(nameof (Loom));
      UnityEngine.Object.DontDestroyOnLoad((UnityEngine.Object) gameObject);
      Loom._current = gameObject.AddComponent<Loom>();
    }

    public static void QueueOnMainThread(Action action)
    {
      Loom.QueueOnMainThread(action, 0L);
    }

    public static void QueueOnMainThread(Action action, long millis)
    {
      if ((UnityEngine.Object) Loom.Current == (UnityEngine.Object) null)
        return;
      if (millis > 0L)
      {
        lock (Loom.Current._delayed)
          Loom.Current._delayed.Add(new Loom.DelayedQueueItem()
          {
            Time = DateTimeUtil.GetNowTicks() + millis * 10000L,
            Action = action
          });
      }
      else
      {
        lock (Loom.Current._actions)
          Loom.Current._actions.Add(action);
      }
    }

    public static void RunAsync(Action a)
    {
      Loom.Initialize();
      lock (Loom.Current._taskQueue)
      {
        if (Loom._numThreads >= Loom.MaxThreads)
        {
          Loom.Current._taskQueue.Enqueue(a);
        }
        else
        {
          ++Loom._numThreads;
          ThreadPool.QueueUserWorkItem(new WaitCallback(Loom.RunAction), (object) a);
        }
      }
    }

    private static void RunAction(object obj)
    {
      LogHelper.Debug("Loom Thread Start, ThreadId: " + (object) Thread.CurrentThread.ManagedThreadId);
      Action action = (Action) obj;
      while (true)
      {
        try
        {
          action();
        }
        catch (Exception ex)
        {
          LogHelper.Error(ex.ToString());
        }
        lock (Loom.Current._taskQueue)
        {
          if (Loom.Current._taskQueue.Count > 0)
          {
            action = Loom.Current._taskQueue.Dequeue();
          }
          else
          {
            --Loom._numThreads;
            break;
          }
        }
      }
      LogHelper.Debug("Loom Thread End, ThreadId: " + (object) Thread.CurrentThread.ManagedThreadId);
    }

    private void OnDisable()
    {
      if (!((UnityEngine.Object) Loom._current == (UnityEngine.Object) this))
        return;
      Loom._current = (Loom) null;
    }

    private void Update()
    {
      lock (this._actions)
      {
        this._currentActions.Clear();
        this._currentActions.AddRange((IEnumerable<Action>) this._actions);
        this._actions.Clear();
      }
      foreach (Action currentAction in this._currentActions)
      {
        try
        {
          currentAction();
        }
        catch (Exception ex)
        {
          LogHelper.Error(ex.ToString());
        }
      }
      long now = DateTimeUtil.GetNowTicks();
      lock (this._delayed)
      {
        this._currentDelayed.Clear();
        this._currentDelayed.AddRange((IEnumerable<Loom.DelayedQueueItem>) this._delayed.FindAll((Predicate<Loom.DelayedQueueItem>) (d => d.Time <= now)));
        foreach (Loom.DelayedQueueItem delayedQueueItem in this._currentDelayed)
          this._delayed.Remove(delayedQueueItem);
      }
      foreach (Loom.DelayedQueueItem delayedQueueItem in this._currentDelayed)
        delayedQueueItem.Action();
    }

    public struct DelayedQueueItem
    {
      public Action Action;
      public long Time;
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值