unity多线程的学习-Loom-Loom类

来源:互联网 发布:域名代理商 编辑:程序博客网 时间:2024/05/29 04:48


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










/// <summary>
/// Primairy accespoint/interface to all framework methods & helpers. This is just a static wrapper-class for sake of ease...
/// </summary>
public static class Loom
{








    //--------------------------------------- 2 START SINGLE THREAD OVERLOADS 两个起始线程重载--------------------------------------
    //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
    #region 2 START SINGLE THREAD OVERLOADS 


    
        
    /// <summary>
    /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
    /// 在新线程上运行方法,当方法停止运行时线程死亡
    /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
    /// 可以利用DispatchToMainThread-actions 和 WaitForNextFrame
    /// </summary>
    /// <param name="targetMethod">The method that will be executed by the new thread</param>
    /// 将被线程执行的目标方法
    /// <param name="priority">Thread Priority</param>
    /// 线程优先级
    /// <param name="safeMode">Default TRUE: Executes the targetMethod within a Try-Catch statement and will log any errors back to the MainThread</param>
    /// try-catch安全模式
    /// <returns>Newly instantiated Thread</returns>
    /// 返回最近的初始化线程
    public static Thread StartSingleThread(ThreadStart targetMethod, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
    {   
        return SingleThreadStarter.StartSingleThread(targetMethod, priority, safeMode);
    } 
    
    




    /// <summary>
    /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
    /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
    /// </summary>
    /// <param name="targetMethod">The method that will be executed by the new thread</param>
    /// <param name="argument">Object to pass to the targetMethod as soon as the Thread is started</param>
    /// 当线程开启时传递给目标方法的参数对象
    /// <param name="priority">Thread Priority</param>
    /// <param name="safeMode">Default TRUE: Executes the targetMethod within a Try-Catch statement and will log any errors back to the MainThread</param>
    /// <returns>Newly instantiated Thread</returns>
    public static Thread StartSingleThread(ParameterizedThreadStart targetMethod, object argument, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
    {
        return SingleThreadStarter.StartSingleThread(targetMethod, argument, priority, safeMode);
    }




    #endregion
    //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
    //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------

























    //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS  4个多线程工作执行重载 --------------------------------------
    //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------


    #region 4 MULTI THREADED WORK EXECUTION OVERLOADS
    /// <summary>
    /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
    /// 分散重复的工作量到多线程去
    /// </summary>
    /// <typeparam name="T">T: Generic-Type of the object you want to be computed by the executor</typeparam>
    /// 泛型对象
    /// <param name="staticWorkloadExecutor"> A (static) method that computes one workLoad-object at a time</param>
    /// 每次计算一份工作对象的静态方法
    /// <param name="workLoad">An array with objects you want to get computed by the executor</param>
    /// 对象数组
    /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
    /// 当全部重打包的工作对象已经完成计算时fired
    /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
    /// 每完成一份工作对象的重打包时fires
    /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
    /// 线程池运行的线程数最大量
    /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
    /// 如果为空,将初始化新的线程池调度器
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// 安全模式:try-catch
    /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
    /// 返回线程池调度器,它处理所有重打包的工作对象
    public static ThreadPoolScheduler StartMultithreadedWorkloadExecution<T>(ThreadWorkloadExecutor<T> workloadExecutor, T[] workLoad, MultithreadedWorkloadComplete<T> onComplete, MultithreadedWorkloadPackageComplete<T> onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
    {
        return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution<ThreadWorkloadExecutor<T>, T>(workloadExecutor, workLoad, null, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
    }






    /// <summary>
    /// 索引
    /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
    /// Besides the workLoad-object, the current index of the workLoad-array is passed to the Executor-delegate.
    /// 除了工作对象,当前对象数组的索引将被传递给委托执行器
    /// </summary>
    /// <typeparam name="T">T: Generic-Type of the object you want to be computed by the executor</typeparam>
    /// <param name="staticWorkloadExecutor"> A (static) method that computes one workLoad-object at a time</param>
    /// <param name="workLoad">An array with objects you want to get computed by the executor</param>
    /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
    /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
    /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
    /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
    public static ThreadPoolScheduler StartMultithreadedWorkloadExecution<T>(ThreadWorkloadExecutorIndexed<T> workloadExecutor, T[] workLoad, MultithreadedWorkloadComplete<T> onComplete, MultithreadedWorkloadPackageComplete<T> onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
    {
        return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution<ThreadWorkloadExecutorIndexed<T>, T>(workloadExecutor, workLoad, null, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
    }




    /// <summary>
    /// 参数
    /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
    /// Besides the workLoad-object, an extra Argument will be passed to the Executor-delegate
    /// 除了工作对象,还有额外的参数
    /// </summary>
    /// <typeparam name="T">T: Generic-Type of the object you want to be computed by the executor</typeparam>
    /// <param name="staticWorkloadExecutor"> A (static) method that computes one workLoad-object at a time</param>
    /// <param name="workLoad">An array with objects you want to get computed by the executor</param>
    /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
    /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
    /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
    /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
    public static ThreadPoolScheduler StartMultithreadedWorkloadExecution<T>(ThreadWorkloadExecutorArg<T> workloadExecutor, T[] workLoad, object extraArgument, MultithreadedWorkloadComplete<T> onComplete, MultithreadedWorkloadPackageComplete<T> onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
    {
        return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution<ThreadWorkloadExecutorArg<T>, T>(workloadExecutor, workLoad, extraArgument, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
    }




    /// <summary>
    /// 参数+索引
    /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
    /// Besides the workLoad-object, an extra Argument & the current index of the workLoad-array is passed to the Executor-delegate.
    /// </summary>
    /// <typeparam name="T">T: Generic-Type of the object you want to be computed by the executor</typeparam>
    /// <param name="staticWorkloadExecutor"> A (static) method that computes one workLoad-object at a time</param>
    /// <param name="workLoad">An array with objects you want to get computed by the executor</param>
    /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
    /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
    /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
    /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
    public static ThreadPoolScheduler StartMultithreadedWorkloadExecution<T>(ThreadWorkloadExecutorArgIndexed<T> workloadExecutor, T[] workLoad, object extraArgument, MultithreadedWorkloadComplete<T> onComplete, MultithreadedWorkloadPackageComplete<T> onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
    {
        return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution<ThreadWorkloadExecutorArgIndexed<T>, T>(workloadExecutor, workLoad, extraArgument, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
    }


    #endregion


    //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------
    //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------















    












    //--------------------------------------- THREAD POOL SCHEDULAR  线程池调度器--------------------------------------
    //--------------------------------------- THREAD POOL SCHEDULAR --------------------------------------


    #region THREAD POOL SCHEDULAR




    /// <summary>
    /// Unlike "StartMultithreadedWorkloadExecution", you will have to build your own IThreadWorkerObject.
    /// 自己创建线程工作者对象
    /// Downside: It requires some extra work. Upside: you got more controll over what goes in and comes out
    /// 缺点:需要额外工作  优点:对线程出入有更多控制
    /// Infact: You can create you own polymorphed IThreadWorkerObject-array, each ellement being a completely different type. For example: the statemachines of enemies are IThreadWorkerObject's and the array contains completely different classes with enemies/AI-behaviours.
    /// 可以创建变形的线程工作者对象数组,每个元素可以是完全不同的类型
    /// </summary>
    /// <param name="workerObjects">An array of IThreadWorkerObject objects to be handled by the threads. If you want multiple cores/threads to be active, make sure that the number of IThreadWorkerObject's proves matches/exeeds your preferred number maxWorkingThreads. </param>
    /// 工作者对象数组,若要使用多线程,确保工作对象数量大于指定的最大线程数??
    /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
    /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
    /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
    /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
    public static ThreadPoolScheduler StartMultithreadedWorkerObjects(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
    {
        if (scheduler == null)
            scheduler = CreateThreadPoolScheduler();


        scheduler.StartASyncThreads(workerObjects, onCompleteCallBack, onPackageExecuted, maxThreads, safeMode);
        return scheduler;
    }






    /// <summary>
    /// Creates an ThreadPoolScheduler instance, which happens to be a Monobehaviour and therefore will showup as gameobject "ThreadPoolScheduler";
    /// 创建线程池调度器实例
    /// </summary>
    /// <returns></returns>
    public static ThreadPoolScheduler CreateThreadPoolScheduler()
    {
        GameObject go = new GameObject("ThreadPoolScheduler");//创建游戏对象
        return go.AddComponent<ThreadPoolScheduler>();//挂载组件
    }




    /// <summary>
    /// Creates an ThreadPoolScheduler instance, which happens to be a Monobehaviour and therefore will showup by the name you provide (default: "ThreadPoolScheduler");
    /// </summary>
    /// <returns></returns>
    public static ThreadPoolScheduler CreateThreadPoolScheduler(string name)
    {
        GameObject go = new GameObject(name == null || name == string.Empty ? "ThreadPoolScheduler" : name);//指定名字,更加灵活
        return go.AddComponent<ThreadPoolScheduler>();
    }




    #endregion


    //--------------------------------------- THREAD POOL SCHEDULAR --------------------------------------
    //--------------------------------------- THREAD POOL SCHEDULAR --------------------------------------






























    //--------------------------------------- THREAD WAIT COMMANDS  线程等待控制--------------------------------------
    //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------


    #region THREAD WAIT COMMANDS


    /// <summary>
    /// Halts/Sleeps the current thread until Unity has rendered a frame. This can be used Coroutine-wise and is safe to be placed within an endless while-loop. Not recommended though...
    /// 停止/休眠当前线程直到Unity提供一帧??,类似协程,适用于while循环
    /// If fired from the MainThread, an error-log will be thrown because its not allowed to freeze the MainThread.
    /// 如果被主线程解除,将会抛出错误提示,因为它不允许freeze主线程
    /// </summary>
    /// <param name="waitFrames">By default set to 1. You can let the Thread wait several frames if needed</param>
    /// 单位为帧,默认为1
    public static void WaitForNextFrame(int waitFrames = 1)
    {
        new ThreadWaitForNextFrame(waitFrames);
    }




    /// <summary>
    /// Halts/Sleeps the current thread until "seconds" has expired. This can be used Coroutine-wise and is safe to be placed within an endless while-loop. Not recommended though...
    /// If fired from the MainThread, an error-log will be thrown because its not allowed to freeze the MainThread.
    /// </summary>
    /// <param name="seconds">Amount of time you want the Thread to sleep.</param>
    /// 单位为秒
    public static void WaitForSeconds(float seconds)
    {
        new ThreadWaitForSeconds(seconds);
    }


    #endregion


    //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------
    //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------



























    //--------------------------------------- 4 DISPATCHER OVERLOADS 四个调度员重载--------------------------------------
    //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------


    #region 4 DISPATCHER OVERLOADS






    /// <summary>
    /// Fire and forget: The MainThread will execute this method witout any arguments to pass, nothing will be returned.
    /// 无参无返回
    /// </summary>
    /// <param name="dispatchCall">Example: "() => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name)" </param>
    /// 调度器调用,输出信息:被主线程解除的当前线程名
    /// <param name="waitForExecution">Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".</param>
    /// 等待执行:挂起线程,等待主线程执行或被解除
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    public static void DispatchToMainThread(ThreadDispatchDelegate dispatchCall, bool waitForExecution = false, bool safeMode = true)
    {
        MainThreadDispatcher.DispatchToMainThread(dispatchCall, waitForExecution, safeMode);
    }




    
    
    /// <summary>
    /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
    /// 有参无返回
    /// </summary>
    /// <param name="dispatchCall">Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"</param>
    /// <param name="dispatchArgument">Once the MainThread executes this action, the argument will be passed to the delegate</param>
    /// <param name="waitForExecution">Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    public static void DispatchToMainThread(ThreadDispatchDelegateArg dispatchCall, object dispatchArgument, bool waitForExecution = false, bool safeMode = true)
    {
        MainThreadDispatcher.DispatchToMainThread(dispatchCall, dispatchArgument, waitForExecution, safeMode);
    }








    /// <summary>     
    /// 有参有返回
    /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
    /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
    /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
    /// </summary>
    /// <param name="dispatchCall">Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"</param>
    /// <param name="dispatchArgument">Once the MainThread executes this action, the argument will be passed to the delegate</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread</returns>
    public static object DispatchToMainThreadReturn(ThreadDispatchDelegateArgReturn dispatchCall, object dispatchArgument, bool safeMode = true)
    {
        return MainThreadDispatcher.DispatchToMainThreadReturn(dispatchCall, dispatchArgument, safeMode);
    }




    /// <summary>
    /// 无参有返回
    /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
    /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
    /// </summary>
    /// <param name="dispatchCall">Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"</param>
    /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
    /// <returns>After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread</returns>
    public static object DispatchToMainThreadReturn(ThreadDispatchDelegateReturn dispatchCall, bool safeMode = true)
    {
        return MainThreadDispatcher.DispatchToMainThreadReturn(dispatchCall, safeMode);
    }
    


    #endregion


    //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
    //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
    














    //--------------------------------------- CHECK UNITY ACTIVITY  核查Unity活动状态--------------------------------------
    //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
    #region CHECK UNITY ACTIVITY


    /// <summary>
    /// A easy way to check if Unity is still running, focused and not pauzed.
    /// 检查unity是否在运行
    /// This comes in handy if threads keep running heavy workloads on seperate threads while IOS for example tries to puch the Application to the background.
    /// 应用在:当线程持续执行繁重工作量时
    /// If you are executing a giant routine on a seperate thread that takes several seconds per cycle, you might want to check regularly if unity is still active by using this check.
    /// 能定期检查unity是否在运行
    /// </summary>
    /// <returns>Returns TRUE if Unity is still running, not pauzed and has focus. </returns>
    /// 返回布尔值
    public static bool CheckUnityActive()
    {
        return UnityActivityWatchdog.CheckUnityActive();
    }








    /// <summary>
    /// !IMPORTANT! This method should be called regularly within routines that take more then half a second to complete, to make sure IOS for example is able to force an application to sleep when it looses focus or gets puched to the background.
    /// 这个方法将被定期调用
    /// This is a very light-weight check, internally it only needs to check two static booleans once everything is Initialized and running.
    /// 轻量级程序,本质上当程序已经初始化并且在运行时只要检查两个静态布尔值
    /// You can use this without causing any serious overhead.
    /// 消耗不大
    /// Motivation: Sins Threads cannot be put asleep from the outside, it needs the be managed from within the thread itself, thats why this method was build.
    /// 出问题线程不能从外界被唤醒,只能从线程本身进行管理
    /// Example:
    /// for(int i = 0; i < 999999999; i++)
    /// {
    ///     Loom.SleepOrAbortIfUnityInactive(); //Prevents IOS for example of killing this app because the threads won't sleep once your unity-app is puched to the background.
    ///     //Do something heavy that will cause this routine to run more then 0.5 seconds.
    /// }
    /// </summary>
    public static void SleepOrAbortIfUnityInactive()
    {
        UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
    }
    #endregion
    //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
    //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------



















    //--------------------------------------- MAIN THREAD WATCHDOG  主线程监测器--------------------------------------
    //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
    #region MAIN THREAD WATCHDOG


    /// <summary>
    /// If you need your current code to be running on the MainThread, you can always call this method to check if its the MainThread or not...
    /// 如果当前代码需要被主线程执行,你可以调用这个方法检查它是否是主线程
    /// </summary>
    /// <returns>Returns TRUE if its the MainThread</returns>
    /// 若是主线程返回true
    public static bool CheckIfMainThread()
    {
        return MainThreadWatchdog.CheckIfMainThread();
    }




    #endregion
    //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
    //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------

}
0 0
原创粉丝点击