Search Unity

Help with thread logic _ need to be on the main thread

Discussion in 'Scripting' started by Thibault-Potier, Jan 11, 2019.

  1. Thibault-Potier

    Thibault-Potier

    Joined:
    Apr 10, 2015
    Posts:
    206
    Hi

    Here is my current situation:

    When pressing a button, i'm creating a random positionned drone with random id.
    Then i give this drone to my drone manager which has a function :
    Code (CSharp):
    1. public void UpdtateFleet(Drone_Dev drone)
    This function will do stuff (is it a new drone, or is it an update of the position of a drone that i already know (because of the id)). Aniway. At the end of this function i'm triggering an event

    Code (CSharp):
    1. public delegate void OnFleetChangeDelegate(Drone_Dev newDrone);
    2.     public event OnFleetChangeDelegate OnFleetChange;
    Then on another script i'm listening to this event, which allow me to deal with the drone gameobject creation / position update.

    This is working perfectly fine in this scenario.

    2nd scenario:
    i'm not creating random value for drone creation by pressing a button, but by receiving those value through network.
    I'm receiving a network message, that i'm reading to decide what to do, and if it's about a drone i'm calling the same function UpdtateFleet(Drone_Dev drone) as i was in the first scenario.

    BUT now at the end of this story (networkmanager -> DroneManager -> event -> creation of gameobject)
    i run into some troubles because i'm not anymore on the main thread.

    As i'm not very familiar with threads / networks i'm a bit lost about what to do to fix this.

    How can i "return" to the main thread after firing my event ? Is there something wrong about my game logic ? How am i suppose to handle things ?
     
  2. Thibault-Potier

    Thibault-Potier

    Joined:
    Apr 10, 2015
    Posts:
    206
    Well, i found a way to make it work.

    Based on this amazing blog :
    https://blog.theknightsofunity.com/using-threads-unity/

    So i have added this tool :
    https://github.com/nickgravelyn/UnityToolbag/blob/master/Dispatcher/Dispatcher.cs

    and in my UpdtateFleet function i'm now doing :
    Code (CSharp):
    1. Dispatcher.Invoke(() =>
    2.         {
    3.             // this code is executed in main thread
    4.             OnFleetChange(drone);
    5.         });
    to fire my event.

    It's working :)

    I'm still open to discussion about the best way to go though. And i cross my finger for this to work on android device as well
     
  3. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Yeah, that looks like the best way. It's pretty similar to what I do when I need threading (haven't looked into the job system yet).
    public ConcurrentQueue<Action> mainThreadActions = new ConcurrentQueue<Action>();

    Then Update will process everything in the queue, and other threads add actions to the queue.
    Unity's Job system looks promising though, that might be worth looking into.
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I've build a solution that wraps a (one parameter) delegate that needs to be executed in the main thread with another delegate. The code on that side is not very pretty, but the use is fairly pretty.
    Code (csharp):
    1.  
    2. ExecuteWithCallback(Async.MainThread<float>(MyDelegate));
    3.  
    4. private void MyDelegate(float result)
    5. {
    6.     // This gets executed on the main thread only.
    7. }
    8.  
    It works in a similar way by calling from Update, but you can directly wrap any (one parameter) delegate this way. The static MainThread<T> method returns an Action<T> and takes an Action<T> as parameter.
     
  5. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    There's also Rx approach that can be done with UniRx. Simply use .ObserveOnMainThread() on the subscription and you're good to go.

    Under the hood it still uses a main thread dispatcher, so it's not much of a different.