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