- Home /
Invoking main thread
I've seen alot of posts on how the Unity3d engine isn't thread safe. However very few posts on how you can safely use multi-threading within Unity3d. If the engine wasn't designed for multi-threading adding the current check is the only right thing to do. However that doesn't mean threading isn't supported! Or isn't safe. It just means that Unity3d won't try to handle all the weird race conditions that threading involves.
I'm currently making a small MMO (what an oxymoron I know!) never the less I feel I've narrowed the project enough that its not a monomental achievement. Blog with project outline
Now let me make it clear. I'm not using multi-threading cause its cool. Or because I have huge calculations. I use it cause most actions needs to swing by a server to be validated and/or randomized! I'm using the ASP.Net client generated by mono's wsdl and it has two modes, blocking and async. I'm going for async and that means I get my replies in a different thread.
First I looked for methods to invoke back to main thread, but found none. Even more so I found several posts saying I'm a dummy cause I insist on using threads. :)
Well luckily I previously did an advanced CommandQueue system. It works a bit like co-routines, it takes a bit longer to define you commands, however its slightly better suited for scripted animations and such. But the main advantage ofcourse is that it allows me to add commands in a thread-safe way and then execute them in main thread.
So my two cents to all with a similar problem. Make an abstract object with an abstract run() method. Then derive an object from that which holds the needed context information (perhaps a delegate to invoke) add it to a thread-safe list. You can then run through the list on Update() and voila!
Alternate/Simpler solutions:
GabrielH suggests adding coroutines to a list and then starting the coroutine from main-thread.
If you just want a quick fix take PragmaScript's solution cause it has source code. Though I'd recommend swapping the list with an empty one. Then you can release the lock and call the actions without risking thread-locking issues.
Since I'm new with Unity3d I hope someone can point me towards the new feature suggestions page. Cause an InvokedCoroutine that calls the coroutine on main-thread would certainly solve most user problems.
Uhm. Is this actually a question? If not, please use our forums ins$$anonymous$$d. FWIW, features can be suggested at feedback.unity3d.com.
While not exactly a question, it represents some knowledge I looked for without success in this section earlier.
It is fine and appreciated to add knowledge to this site to share it with other people. However, to keep this useful, please stick to the Q & A format. Just post a question, and write your own reply (which you can then later accept). That way people searching for information will more likely look at your question, seeing that it has an accepted reply, and people looking to help other people will be able to skip reading it, seeing that it alread has an answer. Thanks, jonas.
btw what forum would you put this into? Seems there is no knowledge base forum. The closest thing I came was the scripting forum and to be honest I don't feel thats the right forum. Welcome message second line: "You couldn't script it, could you? Well, maybe if..."
If you need a language tutorial, then I'd wait another month before starting on threads.
Answer by UnLogick · Jun 11, 2011 at 08:35 PM
I accidentally wrote the answer in the question.
So my two cents to all with a similar problem. Make an abstract object with an abstract run() method. Then derive an object from that which holds the needed context information (perhaps a delegate to invoke) add it to a thread-safe list. You can then run through the list on Update() and voila!
Alternate/Simpler solutions:
PragmaScript suggests a list of actions. Word of warning, his sample keeps the list locked while the actions are executing. When a project grows big enough someone will cause a deadlock on that.
GabrielH suggests adding coroutines to a list and then starting the coroutine from main-thread.
If you just want a quick fix take PragmaScript's solution cause it has source code.Though I'd recommend swapping the list with an empty one. Then you can release the lock fast such reducing the chances of a thread halting and waiting.
Answer by pdwitte · Apr 02, 2016 at 05:24 AM
Hey guys,
I created a simple class for this reason that you can call with a one-liner.
You can use it like this:
public IEnumerator ThisWillBeExecutedOnTheMainThread() {
Debug.Log ("This is executed from the main thread");
yield return null;
}
public void ExampleMainThreadCall() {
UnityMainThreadDispatcher.Instance().Enqueue(ThisWillBeExecutedOnTheMainThread());
}
Simply head over to https://github.com/PimDeWitte/UnityMainThreadDispatcher and start using it if you'd like.
Answer by PaulUsul · Jun 10, 2011 at 10:07 AM
Since I'm new with Unity3d I hope someone can point me towards the new feature suggestions page
Only question I could find :)
Answer by Tom 17 · Jun 10, 2011 at 10:17 AM
Invoking the main thread is indeed a peculiar way to call what you are up to. Here is my two cents in the best hope that this helps you.
So whatever the layout of your threading may be, I will focus on the point where you need to synch anything that calls Unity-API with the main thread. Coroutines aren't really a seperate thread, they are executed on the main thread just as well. But you can yield their execution and wait for the end of the current frame (WaitForEndOfFrame). As I see it that's the place where you should synch. The way I would go is to have a script that starts a coroutine which yields for the end of a frame and invoke a delegate. this delegate could be filled with actions/task, whatever you will call it, by seperate threads. This way you can have an asynchronous thread that handles stuff that needs to be authorized by the server and you feed the results back in the game loop by adding some methods to the delegate.
This is not a complete system, but I hope it gets you started.
Hey $$anonymous$$
Well its called invoke in WinForms. You take any given System.Windows.Forms.Control and use the Invoke(Delegate) method to have it call a delegate from its thread. How fast the delegate is called depends on when that thread reaches its message loop. In unity that could be once every frame which is perfect for my needs.
Seems to me that WaitForEndOfFrame is a coroutine method used to plan changes that will take effect after this frame, or to grab screenshots. If it works outside of the main thread(unlikely) all it does is alter the odds of the thread lock collision. But while that might work on most systems, it could make a collision 99% of the time on another system.
Oh I almost forgot, you can't create a co-routine from a thread. So in order to use the co-routine I'd have to first sync up. The only advantage of a co-routine after sync is that it gives more flexibility than a delegate.