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