Unity与MultiThread、Async vs. coroutines

Best practices: Async vs. coroutines - Unite Copenhagen

              

 

 

////////////////// UnityMultithreading//////////////////////////////////////

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Threading;

using System;

 

public class ThreadQueuer : MonoBehaviour

{

 

    void Start()

    {

        // BIG HUGE NOTE:     WebGL doesn't do multithreading.

 

        Debug.Log("Start() -- Started.");

        functionsToRunInMainThread = new List<Action>();

 

        StartThreadedFunction( () => { SlowFunctionThatDoesAUnityThing( Vector3.zero, new float[4], new Color[100] ); } );

 

        Debug.Log("Start() -- Done.");

    }

 

    void Update()

    {

        // Update() always runs in the main thread

 

        while(functionsToRunInMainThread.Count > 0)

        {

            // Grab the first/oldest function in the list

            Action someFunc = functionsToRunInMainThread[0];

            functionsToRunInMainThread.RemoveAt(0);

 

            // Now run it

            someFunc();

        }

    }

 

    List<Action> functionsToRunInMainThread;

 

    public void StartThreadedFunction( Action someFunctionWithNoParams )

    {

        Thread t = new Thread( new ThreadStart( someFunctionWithNoParams ) );

        t.Start();

 

 

    }

 

    public void QueueMainThreadFunction( Action someFunction )

    {

        // We need to make sure that someFunction is running from the

        // main thread

 

        //someFunction(); // This isn't okay, if we're in a child thread

 

        functionsToRunInMainThread.Add(someFunction);

    }

 

    void SlowFunctionThatDoesAUnityThing( Vector3 foo, float[] bar, Color[] pixels )

    {

        // First we do a really slow thing

        Thread.Sleep(2000); // Sleep for 2 seconds

 

        // Now we need to modify a Unity gameobject

        Action aFunction = () => {

            Debug.Log("The results of the child thread are being applied to a Unity GameObject safely.");

            this.transform.position = new Vector3(1,1,1);   // NOT ALLOWED FROM A CHILD THREAD

        };

 

        // NOTE: We still aren't allowed to call this from a child thread

        //aFunction();

 

        QueueMainThreadFunction( aFunction );

    }

}

http://quill18.com/unity_tutorials/

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Threading;

 

public class ExampleScript : MonoBehaviour

{

    void Start ()

    {

        Debug.Log("Start() :: Starting.");

 

        foo = "Computer Science";

 

        someVector = new Vector3(1, 1, 1);

 

 

        // SlowJob is a variable that contains some function code

        // When you add the () at the end of the SlowJob variable

        // name, that's a shortcut to tell C# "execute the contents of variable SlowJob"

 

        myThread = new Thread( SlowJob );

 

        // Now run SlowJob in a new thread

        myThread.Start();

 

        Debug.Log("Start() :: Done.");

    }

 

    Thread myThread;

 

    void Update()

    {

        if( myThread.IsAlive )

        {

            Debug.Log("SlowJob isRunning");

        }

        else

        {

            // The thread is done, so copy the pixels back to the texture

            someTexture.SetPixels(pixels);

        }

 

        someVector = new Vector3(2, 2, 2);

 

        Vector3 pos = this.transform.position;

        pos.x = 3;

        this.transform.position = pos;

 

        //this.transform.Translate( Vector3.up * Time.deltaTime );

 

        pixels = someTexture.GetPixels();

    }

 

    Texture2D someTexture;

    Color[] pixels;

 

    void PrintStudentID()

    {

        // This send "foo" to the printer

        // This should print out    "Computer Science"

        // Or maybe it'll print out "English Literature"

        // Either is legit

        // What isn't legit is if in the MIDDDLE of printing, the

        // other thread makes a change and suddenly we get a

        // student ID that says:    "Compute Literature"

 

        // Let's make sure no one is changing our data mid-way through

        // our printing operation.

 

        lock(FrontDoor)

        {

            // Print out the student ID here, safe in the

            // knowledge that nothing is messing with our data.

        }

 

    }

 

    void FixedUpdate()

    {

       

    }

 

    string foo;

 

    Vector3 someVector;

 

    object FrontDoor = new object();

 

    void SlowJob()

    {

        Debug.Log("ExampleScript::SlowJob() -- Doing 1000 things, each taking 2ms.");

 

        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        sw.Start();

 

        someVector = new Vector3(0, 0, 0);

 

        for (int i = 0; i < 1000; i++)

        {

           

            Thread.Sleep(2);    // Sleep for 2ms

 

        }

 

        sw.Stop();

 

        // NOTE: Because of various overheads and context-switches, elapsed time

        // will be slightly more than 2 seconds.

        Debug.Log("ExampleScript::SlowJob() -- Done! Elapsed time: " + sw.ElapsedMilliseconds/1000f);

 

    }

}

 

////////////其他的loom////////////////////////////////////

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;

        //private int _count;

        public static Loom Current

        {

            get

            {

                Initialize();

                return _current;

            }

        }

 

        void Awake()

        {

            _current = this;

            initialized = true;

        }

 

        static bool initialized;

 

        public static void Initialize()

        {

            if (!initialized)

            {

 

                if (!Application.isPlaying)

                    return;

                initialized = true;

                var g = new GameObject("Loom");

                _current = g.AddComponent<Loom>();

#if !ARTIST_BUILD

                UnityEngine.Object.DontDestroyOnLoad(g);

#endif

            }

 

        }

        public struct NoDelayedQueueItem

        {

            public Action<object> action;

            public object param;

        }

 

        private List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>();

        public struct DelayedQueueItem

        {

            public float time;

            public Action<object> action;

            public object param;

        }

        private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();

 

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

 

        public static void QueueOnMainThread(Action<object> taction, object tparam)

        {

            QueueOnMainThread(taction, tparam, 0f);

        }

        public static void QueueOnMainThread(Action<object> taction, object tparam, float time)

        {

            if (time != 0)

            {

                lock (Current._delayed)

                {

                    Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = taction, param = tparam });

                }

            }

            else

            {

                lock (Current._actions)

                {

                    Current._actions.Add(new NoDelayedQueueItem { action = taction, param = tparam });

                }

            }

        }

 

        public static Thread RunAsync(Action a)

        {

            Initialize();

            while (numThreads >= maxThreads)

            {

                Thread.Sleep(100);

            }

            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<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>();

 

        // Update is called once per frame

        void Update()

        {

            if (_actions.Count > 0)

            {

                lock (_actions)

                {

                    _currentActions.Clear();

                    _currentActions.AddRange(_actions);

                    _actions.Clear();

                }

                for (int i = 0; i < _currentActions.Count; i++)

                {

                    _currentActions[i].action(_currentActions[i].param);

                }

            }

 

            if (_delayed.Count > 0)

            {

                lock (_delayed)

                {

                    _currentDelayed.Clear();

                    _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));

                    for (int i = 0; i < _currentDelayed.Count; i++)

                    {

                        _delayed.Remove(_currentDelayed[i]);

                    }

                }

 

                for (int i = 0; i < _currentDelayed.Count; i++)

                {

                    _currentDelayed[i].action(_currentDelayed[i].param);

                }

            }

        }

}

using UnityEngine;

using System.Collections;

using UnityEngine.UI;

using System.Threading;

public class testLoom : MonoBehaviour

{

 

    public Text mText;

    void Start ()

    {

 

        // 用Loom的方法调用一个线程

        Loom.RunAsync(

            () =>

            {

                Thread thread = new Thread(RefreshText);

                thread.Start();

            }

            );

    }

 

    void Update ()

    {

 

    }

    private void RefreshText()

    { 

        // 用Loom的方法在Unity主线程中调用Text组件

        Loom.QueueOnMainThread((param) =>

            {

                mText.text = "Hello Loom!";

            },null);

    }

}

发布了16 篇原创文章 · 获赞 44 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/Game_jqd/article/details/103809518
今日推荐