Search code examples
c#multithreadingunity-game-enginebackgroundworker

Invoking a function in main thread via background thread in Unity


I'm using the following code to retrieve data from the server in the background.

new Thread(retrieveData()).Start();

Following is the function that receives the data from the server,

void retrieveData()
{
    while (true)
    {
        string data = subSocket.ReceiveFrameString();
       
    }
}

I want to create a prefab based on the data that was received from the server. Unfortunately, I can not do so from the background thread that is using retrieveData. How can I send a callback to the mainthread and create a prefab at the specified position?


Solution

  • There are multiple ways probably.

    The most commonly used is a so called "Main Thread Dispatcher" pattern which might look like e.g.

    // An object used to LOCK for thread safe accesses
    private readonly object _lock = new object();
    // Here we will add actions from the background thread
    // that will be "delayed" until the next Update call => Unity main thread
    private readonly Queue<Action> _mainThreadActions = new Queue<Action>();
    
    private void Update () 
    {
        // Lock for thread safe access 
        lock(_lock)
        {
            // Run all queued actions in order and remove them from the queue
            while(_mainThreadActions.Count > 0)
            {
                var action = _mainThreadActions.Dequeue();
    
                action?.Invoke();
            }
        }
    }
    
    void retrieveData()
    {
        while (true)
        {
            var data = subSocket.ReceiveFrameString();
       
    
            // Any additional parsing etc that can still be done on the background thread
    
            // Lock for thread safe access
            lock(_lock)
            {
                // Add an action that requires the main thread
               _mainThreadActions.Enqueue(() =>
                {
                    // Something that needs to be done on the main thread e.g.
                    var text = new GameObject("Info").AddComponent<Text>();
                    text.text = Data;
                }
            }
        }
    }