Unity Loom的多线程

原文转载,只为分享,感谢原博主,https://blog.csdn.net/wlz1992614/article/details/52326881 

1.Loom的原理
Loom继承自MonoBehaviour,在Unity流程管理中Update方法下检查需要回调的Action进行加锁并回调,确保在主线程执行,回调序列本身又作为静态数据保存,在任意线程调用添加,简单轻量

2.初始化优化
原版Loom的初始化方法较为繁琐,每个场景都需要进行初始化,其实可以使用Unity的永不销毁方法来将Loom作为一个永久物体保存下来。 
这样,只需在初始化时的主线程中调用一次 
Loom.Initialize(); 
之后在任意场景任意线程均可调用 
Loom.QueueOnMainThread(()=>{ 
}); 
来完成主线程的操作
 

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

public class Loom : MonoBehaviour  
{  
    public static int maxThreads = 8;  
    static int numThreads;

    private static Loom _current;
    public static Loom Current  
    {  
        get  
        {  
            Initialize();  
            return _current;  
        }  
    }  
    //####去除Awake
//  void Awake()  
//  {  
//      _current = this;  
//      initialized = true;  
//  }  

    static bool initialized;  

    //####作为初始化方法自己调用,可在初始化场景调用一次即可
    public static void Initialize()  
    {  
        if (!initialized)  
        {  

            if(!Application.isPlaying)  
                return;  
            initialized = true;  
            GameObject g = new GameObject("Loom");  
            //####永不销毁
            DontDestroyOnLoad (g);
            _current = g.AddComponent<Loom>();  
        }  

    }  

    private List<Action> _actions = new List<Action>();  
    public struct DelayedQueueItem  
    {  
        public float time;  
        public Action action;  
    }  
    private List<DelayedQueueItem> _delayed = new  List<DelayedQueueItem>();  

    List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();  

    public static void QueueOnMainThread(Action action)  
    {  
        QueueOnMainThread( action, 0f);  
    }  
    public static void QueueOnMainThread(Action action, float time)  
    {  
        if(time != 0)  
        {
            if (Current != null)
            {
                lock (Current._delayed)
                {
                    Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
                }
            }
        }  
        else  
        {
            if (Current != null)
            {
                lock (Current._actions)
                {
                    Current._actions.Add(action);
                }
            }
        }  
    }  

    public static Thread RunAsync(Action a)  
    {  
        Initialize();  
        while(numThreads >= maxThreads)  
        {  
            Thread.Sleep(1);  
        }  
        Interlocked.Increment(ref numThreads);  
        ThreadPool.QueueUserWorkItem(RunAction, a);  
        return null;  
    }  

    private static void RunAction(object action)  
    {  
        try  
        {  
            ((Action)action)();  
        }  
        catch  
        {  
        }  
        finally  
        {  
            Interlocked.Decrement(ref numThreads);  
        }  

    }  


    void OnDisable()  
    {  
        if (_current == this)  
        {  

            _current = null;  
        }  
    }  

    // Use this for initialization  
    void Start()  
    {  

    }  

    List<Action> _currentActions = new List<Action>();  

    // Update is called once per frame  
    void Update()  
    {  
        lock (_actions)  
        {  
            _currentActions.Clear();  
            _currentActions.AddRange(_actions);  
            _actions.Clear();  
        }  
        foreach(var a in _currentActions)  
        {  
            a();  
        }  
        lock(_delayed)  
        {  
            _currentDelayed.Clear();  
            _currentDelayed.AddRange(_delayed.Where(d=>d.time <= Time.time));  
            foreach(var item in _currentDelayed)  
                _delayed.Remove(item);  
        }  
        foreach(var delayed in _currentDelayed)  
        {  
            delayed.action();  
        }  

    }  
}  
 

发布了233 篇原创文章 · 获赞 7 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/china_squirrel/article/details/96742751