Why iTween move does not work inside the thread?

Following is my code, and there i have marked two different positions where iTween is working and not working. And in the end you can find the error given.

public class guestListener{

    private bool mRunning;
    string msg = "";
    Thread mThread;
    TcpListener tcp_Listener = null;
    public GameObject point;
    public int ponit_x, point_y;
	

    public void Begin(GameObject go){
	point = go;
	mRunning = true;
		
	mThread = new Thread (()=>SayHello(point));
  	mThread.Start();
		
        Debug.Log("Thread done...");
	iTween.MoveTo(point,iTween.Hash("x",1)); // <<<<-- THIS WORKS
    }

    public void stopListening(){
        mRunning = false;
    }
	
    void SayHello(GameObject point){
        try{
            tcp_Listener = new TcpListener(54321);
            tcp_Listener.Start();
            System.Console.WriteLine("Server Start");
            Debug.Log("Server Start");
            while (mRunning) {
            if (!tcp_Listener.Pending())
                {
                    Thread.Sleep(100);
                }
            else
                {
                    Debug.Log("1");
                    TcpClient client = tcp_Listener.AcceptTcpClient();
                    Debug.Log("2");
                    NetworkStream ns = client.GetStream();
                    Debug.Log("3");
                    StreamReader reader = new StreamReader(ns);
                    Debug.Log("4");
                    msg = "Woo";
	       	    while (msg!=""){
		       msg = reader.ReadLine();
		       Debug.Log(msg);
		       iTween.MoveTo(point,iTween.Hash("x",2)); //<< THIS IS NOT WORKING
		       Debug.Log("5");
		   }
                    reader.Close();
                    client.Close();
                }
            }
        }
        catch (ThreadAbortException)
        {
            //print("exception");
        }
        finally
        {
            mRunning = false;
            tcp_Listener.Stop();
        }
    }

    void OnApplicationQuit()
    {
        // stop listening thread
        stopListening();
        // wait fpr listening thread to terminate (max. 500ms)
        mThread.Join(500);
    }

}

//=========== Error Report ==================

UnityEngine.Random:RandomRangeInt(Int32, Int32)
UnityEngine.Random:Range(Int32, Int32) (at C:\BuildAgent\work\842f9557127e852\Runtime\ExportGenerated\Editor\UnityEngineRandom.cs:22)
iTween:GenerateID() (at Assets\Standard Assets\Plugins\iTween.cs:6783)
iTween:Launch(GameObject, Hashtable) (at Assets\Standard Assets\Plugins\iTween.cs:6734)
iTween:MoveTo(GameObject, Hashtable) (at Assets\Standard Assets\Plugins\iTween.cs:1448)
guestListener:SayHello(GameObject) (at Assets\Scripts\guestListener.cs:71)
guestListener:m__0() (at Assets\Scripts\guestListener.cs:22)

The reason the errors get thrown is that a separate thread attempts to call functions that are a part of the Unity API and which inherit from UnityEngine.Object. Some of the API (in UnityEngine) is in fact available to separate threads - this counts the instantiation of Color objects, or calling the static methods in Mathf, for instance. You can even write to the console with Debug.Log from separate threads. But other than that, most of the API is off limits to separete threads. A simple way to think about it is this: If it affects something that is visually on the screen, like scaling a Transform, setting a Material’s Texture, Destroying a GameObject, etc, it’s nogo in separate threads.

In order to get around this and still benefit from a threads ability to offload work from the CPU and keep it happily rendering frames, you have to make the separate worker thread interact with the mainthread so that the mainthread calls the appropriate Unity API functions after the worker thread has finished working on whatever it was doing.

This can be done by setting a boolean variable that the mainthread polls in its Update-loop, to tell it when the worker thread is done. In your case, you have a thread which is a server wait for data to arrive, and then you’d like to move a gameObject based on a position that gets sent over the network. So, instead of calling iTween.MoveTo directly in the worker thread, you can set two variables, a boolean, let’s call it “TimeToMove”, and the position, call it “NewPosition”, and then in the mainthread’s Update-loop, do something like the following.

Boolean TimeToMove = false;
Vector3 NewPosition;

void Update()
{
    if (TimeToMove)
    {
        iTween.MoveTo(point, NewPosition);
        TimeToMove = false;
    }
}

void WorkerThread()
{
    while (mRunning) {
        if (!tcp_Listener.Pending())
            {
                Thread.Sleep(100);
            }
        else
            {
                Debug.Log("1");
                TcpClient client = tcp_Listener.AcceptTcpClient();
                Debug.Log("2");
                NetworkStream ns = client.GetStream();
                Debug.Log("3");
                StreamReader reader = new StreamReader(ns);
                Debug.Log("4");
                msg = "Woo";
               while (msg!=""){
          msg = reader.ReadLine();
          Debug.Log(msg);
          NewPosition = iTween.Hash("x",2);
          Debug.Log("5");
          TimeToMove = true;
      }
}

Keep in mind that the above is totally untested and should only serve as a guideline, to give you an idea what I mean. It’s possible it isn’t allowed to call iTween.Hash either, but I’m hoping it is, because it looks like it’s just parsing data out of the string for you, and not messing with Unity. If it doesn’t work, you might have to parse the point out manually.

Best of luck!