2

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); }); 
6
  • The second parameter of socket.On( is a function, there You can't use yield. Maybe you can use flag and start a coroutine like StartExample and wait for the connection with something like: "while(flagNotReady) { yield return null; }" Commented May 18, 2015 at 13:07
  • that's my problem. I don't want to use coroutines because I'm gonna have lots of listeners in my code. Flags and coroutines will make my code becomes unclean and hard to be maintained. Commented May 18, 2015 at 13:34
  • 1
    Have you considered using something like Promises? Commented May 18, 2015 at 14:27
  • @AtraViator I've just googled it, seems like it's more about callbacks handling or executing functions sequentially, great extension btw. But I'm struggling with how to jump to UI thread from current thread (my code above, socket.On listener was running on a background thread), because Unity APIs only run on mainthread. Commented May 19, 2015 at 1:20
  • 1
    @FlySoFast In a previous project of mine, we used uPromise. By resolving the promise inside your background thread socket connect action, and providing the actual code to execute inside the .Done() of a promise (Which is declared on the main thread), you can then run code on the UI thread. It's not quite the same as 'jumping thread' inside the same code block, but it can provide a maintainable codebase and did for my project. If you're interested I can provide a real answer below with code example. Commented May 19, 2015 at 9:12

4 Answers 4

4

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.

Sign up to request clarification or add additional context in comments.

Comments

4

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); 

Comments

3

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!

1 Comment

@seaders please provide your own answer since you have a different function call.
1

Since the answer seems to be not documented on the site, here is my working solution (not thoroughly tested).

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.