Loadimage Texture at runtime


I want to update an image of a texture at runtime, but not in start().
I receive some image by socket, and I want to load this image in a texture.
How can I do ? There is an error, Unity want I call this function in stat() or MainThread. WebCamTexture do this, so I hope I can.


private void ReceiveCallback(IAsyncResult AR)
    //Check how much bytes are recieved and call EndRecieve to finalize handshake
    int recieved = _clientSocket.EndReceive(AR);

    if (recieved <= 0)

    //Copy the recieved data into new buffer , to avoid null bytes
    byte[] recData = new byte[recieved];
    Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);

        var base64EncodedBytes = System.Convert.FromBase64String(Encoding.ASCII.GetString(recData, 0, recieved));
        Stream str = new MemoryStream(base64EncodedBytes);//, 0, bytesRec);

        StartCoroutine("Test", text);

        Mg.mainTexture = text;

        //Image img = System.Drawing.Image.FromStream(str);
        //pictureBox2.Image = img;
    catch (Exception ex)
        //label3.Text = ex.ToString();

    //Process data here the way you want , all your bytes will be stored in recData

    //Start receiving again
    _clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
    byte[] msg = Encoding.ASCII.GetBytes("30");

Error message :

IsObjectMonoBehaviour can only be
called from the main thread.
Constructors and field initializers
will be executed from the loading
thread when loading a scene. Don’t use
this function in the constructor or
field initializers, instead move
initialization code to the Awake or
Start function.
(at Assets/socket.cs:59)

The exception is raised because you can call LoadImage only in the main thread but your code is running asynchronously through BeginReceive/EndReceive that run in a new thread.

There’s a dispatcher on Github posted by a user that can fit your case: click here. Import the file UnityMainThreadDispatcher.cs in your project and attach it to one of your game objects (i.e. the one that contains also your socket script, there should be only one in a scene).

Then pass the local component instance as state object to BeginReceive (last parameter this instead of null):

_clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), this);

Finally you will have to cast AR.AsyncState back to your script type and enqueue the logic in UnityMainThreadDispatcher:

YourScriptName me = (YourScriptName)AR.AsyncState;
UnityMainThreadDispatcher.Instance().Enqueue(() =>
    me.Mg.mainTexture = me.text;