简体   繁体   中英

How to run functions on main thread without using Coroutine in Unity

I've come across some articles about using coroutine to run functions on main thread, such as Thread Ninja :

 IEnumerator StartExamples()
{
    //Jump to main thread
    yield return Ninja.JumpToUnity; 

    Destroy(someGameObject); //OK

    //Jump back to background thread
    yield return Ninja.JumpBack;  
}

It didn't work on my code since I wanted to jump to main thread from a socket listener.

 SocketIOClient.Client socket;

 IEnumerator StartExamples()
 {
    socket.On("connect", (fn) =>
    {
        WriteLine("\r\nConnected event...\r\n");

        //Jump to main thread
        yield return Ninja.JumpToUnity; //ERROR: couldn't do a yield return 

        Destroy(someGameObject); 

        //Jump back to background thread
        yield return Ninja.JumpBack;  //ERROR: couldn't do a yield return 
    });
 }

So do we have any workaround for this? I wish I could jump to main thread like this:

 Dispatcher.BeginInvoke(() =>
{
    //Unity API
    Destroy(gameObject);
});

As per my comment, using uPromise ;

class Example
{
    private Promise BeginSocketConnection()
    {
        Deferred retPromise = new Deferred();

        socket.On("connect", (fn) =>
        {
            // We're no longer on the main thread ):
            // But we can resolve our promise!
            retPromise.Resolve();
        });

        return retPromise;
    }

    private void SocketConnectedSuccessfully()
    {
       // Executing on main thread
    }

    private void Start()
    {
        // We start in the main thread
        BeginSocketConnection().Done(x =>
        {
            SocketConnectedSuccessfully();
        });
    }
}

This doesn't allow you to jump between threads within the same codeblock, but by using a callback system you can alert the main thread to execute an action without messy coroutines being started and yielded all over the place. Much nicer to look at and maintain.

I ended up using a very helpful extension called Unity Thread Helper . It's free, and more than enough for my need!

This is the usage:

 UnityThreadHelper.Dispatcher.Dispatch(() =>
        {
            Destroy(a);

        });

NOTICE: Dispatcher is a singleton object, it will be initialized on your first call. You have to do your first call on main thread, because it uses some Unity API.

 private void Start()
{
    var ugly = UnityThreadHelper.Dispatcher;
}

Hope this helps!

If you don't want to use extensions, like uPromise and Unity Thread Helper mentioned in the other comments, and don't want to use MonoBehavior's coroutines, you can also use SynchronizationContext :

// On main thread, during initialization:
var syncContext = System.Threading.SynchronizationContext.Current;

// On socket listener thread
syncContext.Post(_ =>
{
    // This code here will run on the main thread
    Destroy(gameObject);
}, null);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM