Skip to main content
added 226 characters in body
Source Link
Peter
  • 10k
  • 2
  • 33
  • 46

But chances are Unity will support the basic .Net threadpool in an upcoming version. If they do you won't need that part.

But chances are Unity will support the basic .Net threadpool in an upcoming version. If they do you won't need that part.

Source Link
Peter
  • 10k
  • 2
  • 33
  • 46

If you want to work with Unity and threads, you'll need to implement 2 features that are unfortunately absent from Unity: A thread pool and a main thread dispatcher.

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

public class UnityThreadPool : UnityEngine.MonoBehaviour
{       
    Deque<Action> mMainThreadWaitQueue;
    Deque<Action> mCurrentlyProcessing;
    static UnityThreadPool sInstance;
    Pool mPool;

    public void EnqueueOnMain(Action task) { lock (mMainThreadWaitQueue) mMainThreadWaitQueue.AddToBack(task); }
    public void EnqueueOnWorker(Action task) { mPool.QueueTask(task); }
    public static UnityThreadPool Instance {
        get {
            if (sInstance == null)
                sInstance = new UnityEngine.GameObject("ThreadPool").AddComponent<UnityThreadPool>();
            return sInstance;
        }
    }

    void Awake()
    {
        UnityEngine.Debug.Assert(sInstance == null,"Multiple ThreadPools detected.");
        DontDestroyOnLoad(transform.gameObject);
        mPool = new Pool(UnityEngine.SystemInfo.processorCount); 
        mMainThreadWaitQueue = new Deque<Action>(10);
        mCurrentlyProcessing = new Deque<Action>(10);
    }
    void Update()
    {
        lock (mMainThreadWaitQueue) {
            if (mMainThreadWaitQueue.Count == 0)
                return;
            UnityEngine.Debug.Assert(mCurrentlyProcessing.Count == 0);
            mCurrentlyProcessing.InsertRange(0,mMainThreadWaitQueue);
            mMainThreadWaitQueue.Clear();
        }           
        var watch = System.Diagnostics.Stopwatch.StartNew(); // this is the main thread, track time so we don't block it for too long
        while (mCurrentlyProcessing.Count !=  0){
            var action = mCurrentlyProcessing.RemoveFromFront();
            try { action(); } catch (System.Exception e) { UnityEngine.Debug.LogError("Unhandled Exception in MainThread task: " + e.ToString()); }
            if (watch.ElapsedMilliseconds > 10) {
                lock (mMainThreadWaitQueue) { mMainThreadWaitQueue.InsertRange(0,mCurrentlyProcessing); }
                mCurrentlyProcessing.Clear();
                break;
            }
        }
    }        
    void OnDestroy() { mPool.Dispose(); }
}

For an example implementation of Pool see: https://stackoverflow.com/a/436552/1612743