John Smith John Smith - 7 days ago 9
C# Question

unity updating variable from different thread

I am starting to learn some unity and I have a quick question in regards to multithreading.

I have a class which contains an instance of a datamodel class. The primary function of the class is the fetch a remote resource asynchronously and update the datamodel class. Then in the update function the datamodel class is read out and written to some text in a gameobject.

Anyway I am worrying that it could cause some issues related to multithreading since my async updating of the class could run at the same time as the update function causing a race condition. Do I have to wrap access to the class in a mutex?

class Data {
public int Number { get; set; }
public string Name { get; set; }
}

class Network : MonoBehaviour {
private Data d;

public void Start() {
// setting up handler to async fetch data and call provided callback
Networking.GetData(s => ParsePayload(s));
}

private void ParsePayload(string payload) {
d = JsonConvert.DeserializeObject<Data>(payload);
}

public void Update() {
var label = GameObject.Find("textObject").GetComponent<Text>();
label.Text = d.Name;
}
}


So am I right in this or does unity handle this by itself?

thx for any advice!

Answer

So am I right in this or does unity handle this by itself?

You are right in this. It could cause some problems and Unity does not handle this by itself. You are responsible to making sure that only one Thread can access d variable at a time. There are several ways of this but using the lock keyword can accompilsh this.

Since d is updated in the ParsePayload function and accessed in the Update function, you have to use the lock keyword in both functions.

Another unrelated problem is the GameObject.Find("textObject"). This should be done in the Start() function and saved to a variable. Don't do that in the Update function each frame.

class Network : MonoBehaviour
{
    private Data d;
    Text label;

    private System.Object threadLocker = new System.Object();

    public void Start()
    {
        label = GameObject.Find("textObject").GetComponent<Text>();

        // setting up handler to async fetch data and call provided callback
        Networking.GetData(s => ParsePayload(s));
    }

    private void ParsePayload(string payload)
    {
        lock (threadLocker)
        {
            d = JsonConvert.DeserializeObject<Data>(payload);
        }
    }

    public void Update()
    {
        lock (threadLocker)
        {
            label.text = d.Name;
        }
    }
}
Comments