Creating threads in Unity is flakey in the editor.

I’m experiencing some strange behaviour with threads in unity and I’m wondering if there is a way to fix it or if I’m doing something crazy. The issue is that when I create a thread, the code doesn’t actually seem to be executing on a background thread but is instead on the main thread. However, this exact code runs correctly on the first execution after a fresh start of Unity. It appears to happen both on a Mac and a PC, Unity 4.1.2f Pro.

EDIT: Also note, that if you create a standalone build, it always works. It never logs the error case.
EDIT 2: Added a second set of code that behaves the same.

Here are the steps:

  1. Create a new project, add the code below to a script and attach it to an empty game object. Save the scene if you wish.
  2. Hit play, look at the console output. You’ll see something logging like: Thread id: 2 repeatedly.
  3. Stop playing, then hit play again. You’ll see an error log: On the main thread — Thread id: 1 repeatedly.
  4. Close Unity, reopen Unity and run again. It works. Stop, then start. Broken.
  5. Scratch head.

Here is the simple code I’m using on a game object:

using UnityEngine;
using System.Collections;

public class Startup : MonoBehaviour 
{
	public int MainThreadID = -1;
	public bool KeepRunning = true;

	// Use this for initialization
	void Start () 
	{
		MainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
		System.Threading.ThreadPool.QueueUserWorkItem( callback => 
		{
			while (KeepRunning)
			{
				int threadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
				if (threadID == MainThreadID)
					Debug.LogError("On the main thread --- Thread id: "+threadID);
				else
					Debug.Log("Thread id: "+ threadID);

				System.Threading.Thread.Sleep(1000);
			}

			Debug.Log("Exiting...");
		});
	}

	void OnDestroy()
	{
		KeepRunning = false;
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

This version is slightly different and creates a thread, however, the results are the same:

using UnityEngine;
using System.Collections;
using System.Threading;

public class Startup : MonoBehaviour 
{
	public int MainThreadID = -1;
	public bool KeepRunning = true;

	public Thread MyThread;

	// Use this for initialization
	void Start () 
	{
		MainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
		ThreadStart ts = new ThreadStart( ()=> 
		{
			while (KeepRunning)
			{
				int threadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
				if (threadID == MainThreadID)
					Debug.LogError("On the main thread --- Thread id: "+threadID);
				else
					Debug.Log("Thread id: "+ threadID);

				System.Threading.Thread.Sleep(1000);
			}

			Debug.Log("Exiting...");
		});

		MyThread = new Thread(ts);
		MyThread.IsBackground = true;
		MyThread.Start();
	}

	void OnDestroy()
	{
		KeepRunning = false;
		MyThread.Join();
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

It seems you are not actually creating a new thread, as per instructed in http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx , but only queuing your method for the next available thread. I’m suprised this works the first time, because Unity API isn’t thread safe, so I assumed the Unity code didn’t do any threading internally either.