Thread safety in Unity - multithreading

In Unity, the thread cannot operate the object provided by UnityEngine like transform.position etc, which caused an exception that get_transform can only be called from the main thread.
However, these methods can be used in some async function like BeginReceive, so is there anyone can tell me why? The async function is not thread or sth else?
I try the code below:
void Start(){
AsyncCallback callback = new AsyncCallback (demo);
callback.BeginInvoke (null, null, null);
}
void demo(IAsyncResult result){
Debug.Log(Thread.CurrentThread.ManagedThreadId);
Debug.Log(gb.transform.position.ToString());
}
It does throw an exception when I run the code on Unity Editor. However, when I run this code on an Android phone directly, it didn't throw any exception and the code was performed correctly.
The log in applogcat shows that:
Line 13497: 02-20 14:37:49.973 31027 31697 I Unity : 3
Line 13501: 02-20 14:37:49.975 31027 31697 I Unity : (0.0, 0.0, 0.0)
So it seems that the function runs on another thread instead of main thread, so could anyone tell me why transform works on this situation?

Unity doesn't allow calling most API functions from threads other than the main thread, period. All of the event/message processing is actually done on the main thread.
The coroutine system based on IEnumerator is a bit of a hack and doesn't actually allow for multi-threading (keep in mind that even the .NET 4.5 async/await feature doesn't necessarily imply multithreaded execution either).
If calling the UnityEngine API works, you're on the main thread.

UI APIs aren't allowed to be called from a different thread than the UI one.
This simplifies how Unity works behind the scenes and actually makes it faster.
Some async methods are dispatched using an event loop and not a different thread. Just because a method is async it doesn't mean it gets to run on a different thread.
The most obvious example of this in Unity are Coroutines. They do run async, but on the main thread. This is possible because Unity adds all of to a list and executes them every frame.

You can call the Unity API from other threads, but NOT if you're running the game from within the Unity Editor. Release builds do not check which thread the call to the Unity API originated from. I assume they don't bother to avoid the performance hit.
I haven't tested this much myself though. The Unity documentation is quite clear that the API is not thread-safe. Therefore, definitely don't make any property assignments or calls that change the game state from other threads. Merely reading values might be OK, but it depends on the unknown internal caching behavior of UnityEngine, ie. hashtables/dictionaries would be bad for multi-threading.

Related

Update GUI from worker thread works (WinForms), why?

WinForms (VS2015 / .NET 4.6)
In my background thread
System.Threading.Tasks.Task.Run(() =>
{
...
_callback?.Progress("abcd");
...
});
I call the GUI (_callback), which implements an interface in the Form class.
Here, I modify textbox, progressbar, etc values.
void IWorkerCallback.Log(string message)
{
_textBoxLog.AppendText($"{message}{Environment.NewLine}");
++_progressBar.Value;
.... etc...
}
And all works fine!
If I break in with debugger, I could see that the Form.IWorkerCallback.Log() function is executed in the worker thread context (in Threads debug window).
It's said everywhere that you MUST change GUI items only on the GUI thread (where they are created), otherwise you get System.InvalidOperationException exception with cross-thread operation not valid.....
But it works fine for me.
Could you explain, why?
Thanks
Running UI calls from another thread is undefined behavior. It may work or not. To get consistent failure on cross-thread calls set Control.CheckForIllegalCrossThreadCalls = true; in the beginning of the program:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.checkforillegalcrossthreadcalls?view=netframework-4.8
From MSDN documentation:
When a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results. A common invalid thread activity is a call on the wrong thread that accesses the control's Handle property. Set CheckForIllegalCrossThreadCalls to true to find and diagnose this thread activity more easily.
On low Windows API level, cross-thread UI calls that don't use thread local storage or any other thread-specific resources, may be executed successfully. However, we still have thread synchronization problem, so result is also undefined.

NSURLSession dataTaskWithURL

I am using NSURLSession dataTaskWithURL:completionHandler. It looks like completionHandler is executed in a thread which is different than the thread(in my case, it's the main thread) which calls dataTaskWithURL. So my question is, since it is asynchronized, is it possible that the main thread exit, but the completionHandler thread is still running since the response has not come back, which is the case I am trying to avoid. If this could happen, how should I solve the problem? BTW, I am building this as a framework, not an application.Thanks.
In the first part of your question you seem un-sure that the completion handler is running on a different thread. To confirm this let's look at the NSURLSession Class Reference. If we look at the "Creating a Session" section we can see in the description for the following method the answer.
+ sessionWithConfiguration:delegate:delegateQueue:
Swift
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)
Objective-C
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
delegate:(id<NSURLSessionDelegate>)delegate
delegateQueue:(NSOperationQueue *)queue
In the parameters table for the NSOperationQueue queue parameter is the following quote.
An operation queue for scheduling the delegate calls and completion handlers. The queue need not be a serial queue. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.
So we can see the default behavior is to provide a queue whether from the developer or as the default class behavior. Again we can see this in the comments for the method + sessionWithConfiguration:
Discussion
Calling this method is equivalent to calling
sessionWithConfiguration:delegate:delegateQueue: with a nil delegate
and queue.
If you would like a more information you should read Apple's Concurrency Programming Guide. This is also useful in understanding Apple's approach to threading in general.
So the completion handler from - dataTaskWithURL:completionHandler: is running on a different queue, with queues normally providing their own thread(s). This leads the main component of your question. Can the main thread exit, while the completion handler is still running?
The concise answer is no, but why?
To answer this answer this we again turn to Apple's documentation, to a document that everyone should read early in their app developer career!
The App Programming Guide
The Main Run Loop
An app’s main run loop processes all user-related events. The
UIApplication object sets up the main run loop at launch time and uses
it to process events and handle updates to view-based interfaces. As
the name suggests, the main run loop executes on the app’s main
thread. This behavior ensures that user-related events are processed
serially in the order in which they were received.
All of the user interact happens on the main thread - no main thread, no main run loop, no app! So the possible condition you question mentions should never exist!
Apple seems more concerned with you doing background work on the main thread. Checkout the section "Move Work off the Main Thread"...
Be sure to limit the type of work you do on the main thread of your
app. The main thread is where your app handles touch events and other
user input. To ensure that your app is always responsive to the user,
you should never use the main thread to perform long-running or
potentially unbounded tasks, such as tasks that access the network.
Instead, you should always move those tasks onto background threads.
The preferred way to do so is to use Grand Central Dispatch (GCD) or
NSOperation objects to perform tasks asynchronously.
I know this answer is long winded, but I felt the need to offer insight and detail in answering your question - "the why" is just as important and it was good review :)
NSURLSessionTasks always run in background by default that's why we have completion handler which can be used when we get response from Web service.
If you don't get any response explore your request URL and whether HTTPHeaderFields are set properly.
Paste your code so that we can help it
I just asked the same question. Then figured out the answer. The thread of the completion handler is setup in the init of the NSURLSession.
From the documentation:
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)`
queue - A queue for scheduling the delegate calls and completion handlers. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.*
My code that sets up for completion on main thread:
var session = NSURLSession(configuration: configuration, delegate:nil, delegateQueue:NSOperationQueue.mainQueue())
(Shown in Swift, Objective-C the same) Maybe post more code if this does not solve.

How do I Yield() to another thread in a Win8 C++/Xaml app?

Note: I'm using C++, not C#.
I have a bit of code that does some computation, and several bits of code that use the result. The bits that use the result are already in tasks, but the original computation is not -- it's actually in the callstack of the main thread's App::App() initialization.
Back in the olden days, I'd use:
while (!computationIsFinished())
std::this_thread::yield(); // or the like, depending on API
Yet this doesn't seem to exist for Windows Store apps (aka WinRT, pka Metro-style). I can't use a continuation because the bits that use the results are unconnected to where the original computation takes place -- in addition to that computation not being a task anyway.
Searching found Concurrency::Context::Yield(), but Context appears not to exist for Windows Store apps.
So... say I'm in a task on the background thread. How do I yield? Especially, how do I yield in a while loop?
First of all, doing expensive computations in a constructor is not usually a good idea. Even less so when it's the "App" class. Also, doing heavy work in the main (ASTA) thread is pretty much forbidden in the WinRT model.
You can use concurrency::task_completion_event<T> to interface code that isn't task-oriented with other pieces of dependent work.
E.g. in the long serial piece of code:
...
task_completion_event<ComputationResult> tce;
task<ComputationResult> computationTask(tce);
// This task is now tied to the completion event.
// Pass it along to interested parties.
try
{
auto result = DoExpensiveComputations();
// Successfully complete the task.
tce.set(result);
}
catch(...)
{
// On failure, propagate the exception to continuations.
tce.set_exception(std::current_exception());
}
...
Should work well, but again, I recommend breaking out the computation into a task of its own, and would probably start by not doing it during construction... surely an anti-pattern for a responsive UI. :)
Qt simply uses Sleep(0) in their WinRT yield implementation.

Detecting when you're in/out of the main thread in Xamarin.iOS

Is there a way in Xamarin/MonoTouch to detect whether code is being called in the main thread?
I'm looking for something like the equivalent of Java's EventQueue.isEventDispatchThread() -- I've found in Swing programming it's handy to assert that from time to time (or sometimes to assert that it's not) -- making sure that models are consistently updated and read from the EDT, and that long-running calls don't block the UI.
I'd like to do the same in my MonoTouch app, to ensure that various bits of code are/aren't called from the UI, or wrapped in InvokeOnMainThread.
Updated: For anyone coming along later: Obj-C answer from JP below . The Xamarin/MonoTouch equivalent is NSThread.Current.IsMainThread.
I don't know much about Monotouch, but in iOS +[NSThread isMainThread] might be what you're looking for.
Occasionally when writing multithreaded code, I will put in an assert like this:
NSAssert([NSThread isMainThread], #"Method called using a thread other than main!");
The only problem with NSAssert([NSThread isMainThread], errorDesc) is that you BETTER be in the main thread when making this call. If you happen to be in a secondary thread and make the call then your application crashes! So it's kind of pointless.
It's better just to simply use [NSThread isMainThread] then assess the BOOL value it returns.
You can do like this in Monotouch / Xamarin.ios
if (NSThread.Current.IsMainThread)
{
//You are in the MainThread
}
This check is very useful to avoid the error that might occur when trying to modify the UI from a background Thread. Something Like this can be done:
if (NSThread.Current.IsMainThread)
{
DoSomething();
}
else
{
BeginInvokeOnMainThread(() => DoSomething());
}

Does an asynchronous call always create/call a new thread?

Does asynchronous call always create a new thread?
Example:
If JavaScript is single threaded then how can it do an async postback? Is it actually blocking until it gets a callback? If so, is this really an async call?
This is an interesting question.
Asynchronous programming is a paradigm of programming that is principally single threaded, i.e. "following one thread of continuous execution".
You refer to javascript, so lets discuss that language, in the environment of a web browser. A web browser runs a single thread of javascript execution in each window, it handles events (such as onclick="someFunction()") and network connections (such as xmlhttprequest calls).
<script>
function performRequest() {
xmlhttp.open("GET", "someurl", true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
alert(xmlhttp.responseText);
}
}
xmlhttp.send(sometext);
}
</script>
<span onclick="performRequest()">perform request</span>
(This is a nonworking example, for demonstration of concepts only).
In order to do everything in an asynchronous manner, the controlling thread has what is known as a 'main loop'. A main loop looks kind of like this:
while (true) {
event = nextEvent(all_event_sources);
handler = findEventHandler(event);
handler(event);
}
It is important to note that this is not a 'busy loop'. This is kind of like a sleeping thread, waiting for activity to occur. Activity could be input from the user (Mouse Movement, a Button Click, Typing), or it could be network activity (The response from the server).
So in the example above,
When the user clicks on the span, a ButtonClicked event would be generated, findEventHandler() would find the onclick event on the span tag, and then that handler would be called with the event.
When the xmlhttp request is created, it is added to the all_event_sources list of event sources.
After the performRequest() function returns, the mainloop is waiting at the nextEvent() step waiting for a response. At this point there is nothing 'blocking' further events from being handled.
The data comes back from the remote server, nextEvent() returns the network event, the event handler is found to be the onreadystatechange() method, that method is called, and an alert() dialog fires up.
It is worth noting that alert() is a blocking dialog. While that dialog is up, no further events can be processed. It's an eccentricity of the javascript model of web pages that we have a readily available method that will block further execution within the context of that page.
The Javascript model is single-threaded. An asynchronous call is not a new thread, but rather interrupts an existing thread. It's analogous to interrupts in a kernel.
Yes it makes sense to have asynchronous calls with a single thread. Here's how to think about it: When you call a function within a single thread, the state for the current method is pushed onto a stack (i.e. local variables). The subroutine is invoked and eventually returns, at which time the original state is popped off the stack.
With an asynchronous callback, the same thing happens! The difference is that the subroutine is invoked by the system, not by the current code invoking a subroutine.
A couple notes about JavaScript in particular:
XMLHttpRequests are non-blocking by default. The send() method returns immediately after the request has been relayed to the underlying network stack. A response from the server will schedule an invocation of your callback on the event loop as discussed by the other excellent answers.
This does not require a new thread. The underlying socket API is selectable, similar to java.nio.channels in Java.
It's possible to construct synchronous XMLHttpRequest objects by passing false as the third parameter to open(). This will cause the send() method to block until a response has been received from the server, thus placing the event loop at the mercy of network latency and potentially hanging the browser until network timeout. This is a Bad Thing™.
Firefox 3.5 will introduce honest-to-god multithreaded JavaScript with the Worker class. The background code runs in a completely separate environment and communicates with the browser window by scheduling callbacks on the event loop.
In many GUI applications, an async call (like Java's invokeLater) merely adds the Runnable object to its GUI thread queue. The GUI thread is already created, and it doesn't create a new thread. But threads aren't even strictly required for an asynchronous system. Take, for example, libevent, which uses select/poll/kqueue, etc. to make non-blocking calls to sockets, which then fires callbacks to your code, completely without threads.
No, but more than one thread will be involved.
An asynchronous call might launch another thread to do the work, or it might post a message into a queue on another, already running thread. The caller continues and the callee calls back once it processes the message.
If you wanted to do a synchronous call in this context, you'd need to post a message and actively wait for the callback to happen.
So in summary: More than one thread will be involved, but it doesn't necessarily create a new thread.
I don't know about javascript, but for instance in the Windows Forms world, asynchronous invocations can be made without multiple threads. This has to do with the way the Windows Message Pump operates. Basically a Windows Forms application sets up a message queue through which Windows places messages notifying it about events. For instance, if you move the mouse, messages will be placed on that queue. The Windows Forms application will be in an endless loop consuming all the messages that are thrown at it. According to what each message contains it will move windows around, repaint them or even invoke user-defined methods, amongst other things. Calls to methods are identified by delegates. When the application finds a delegate instance in the queue, it happily invokes the method referred by the delegate.
So, if you are in a method doing something and want to spawn some asynchronous work without creating a new thread, all you have to do is place a delegate instance into the queue, using the Control.BeginInvoke method. Now, this isn't actually multithreaded, but if you throw very small pieces of work to the queue, it will look like multithreaded. If, on the other hand you give it a time consuming method to execute, the application will freeze until the method is done, which will look like a jammed application, even though it is doing something.

Resources