I don't want to execute the current instructions in the current processmessage loop, but instead execute it in the next processmessage loop. Is their a good way to do it ? TThread.queue seam to be what i m looking for except that TThread.queue can not be executed from the main Thread :( I m under firemonkey also if it's matter
TThread.Queue() is asynchronous only if it is called in a worker thread. When TThread.Queue() is called in the main thread, it is synchronous instead 1.
To do what you are asking for, you can use TThread.CreateAnonymousThread() or TTask.Run() to create a worker thread that then calls TThread.Queue().
1: please vote on RSP-15427 Add an option to let TThread.Queue() run asynchronously when called by the main UI thread.
Related
Is serial queue faster then synchronized block?
I have two ways to achieve thread safety. I have implemented option-1 but, my supervisor wants me to implement option-2.
Option 1:
synchronized fun doSomething(task: Task){
//task.do()
}
Option 2:
fun doSomething(task: Task){
serialQueue.add(task)
}
Which approach is faster and why? And why two versions exist for single purpose?
In the first option the calling thread acquires the lock on the object that doSomething is called on, then executes the task, holding the lock until it’s done. If another thread wants to execute the same method on the same instance, that thread has to wait for the tasks run by other threads to finish before it can execute the method.
In the second option a thread drops the task in a queue. The thread isn’t held up waiting while the task executes.
Which option to use can be affected by several things, like how long the task takes, how important it is for the task to get done right now as opposed to letting it process through the queue, and whether you're blocking or non-blocking and how much other work that waiting thread could be doing for you.
In iOS, we have GCD and Operation to handle concurrent programming.
looking into GCD we have QoS classes, and they're simple and straight forward, this question is about why DispatchQueue.main.async is commonly used to asynchronies X tasks in the Main Thread.
So when we usually handle updating something in the UI we usually use that function since to prevent any irresponsiveness from the application.
makes me think is writing code inside the UIViewController usually executed in the main thread ?
but also knowing that callback & completionHandler usually execute without specifying on what thread they are in, and the UI never had a problem with that !! so it is on the background ?
How Swift handles this ? and what thread am i writing on by default without specifying anything ?
Since there are more than one question here, let's attempt to answer them one by one.
why DispatchQueue.main.async is commonly used to asynchronies X tasks
in the Main Thread.
Before mentioning a direct answer, make sure that you don't have confusion of understanding:
Serial <===> Concurrent.
Sync <===> Async.
Keep in mind that DispatchQueue.main is serial queue. Using sync or async has nothing to do with determining serialization or currency of a queue, instead they refer to how the task is handled. Thus saying DispatchQueue.main.async means that:
returns control to the current queue right after task has been sent to
be performed on the different queue. It doesn't wait until the task is
finished. It doesn't block the queue.
cited from: https://stackoverflow.com/a/44324968/5501940 (I'd recommend to check it.)
In other words, async means: this will happen on the main thead and update it when it is finished. That's what makes what you said:
So when we usually handle updating something in the UI we usually use
that function since to prevent any irresponsiveness from the
application.
seems to be sensible; Using sync -instead of async- will block the main.
makes me think is writing code inside the UIViewController usually
executed in the main thread ?
First of all: By default, without specifying which thread should execute a chunk of code it would be the main thread. However your question seems to be unspecific because inside a UIViewController we can call functionalities that are not executed on the main thread by specifying it.
but also knowing that callback & completionHandler usually execute
without specifying on what thread they are in, and the UI never had a
problem with that !! so it is on the background ?
"knowing that callback & completionHandler usually execute without specifying on what thread they are in" No! You have to specify it. A good real example for it, actually that's how Main Thread Checker works.
I believe that there is something you are missing here, when dealing when a built-in method from the UIKit -for instance- that returns a completion handler, we can't see that it contains something like DispatchQueue.main.async when calling the completion handler; So, if you didn't execute the code inside its completion handler inside DispatchQueue.main.async so we should assume that it handles it for you! It doesn't mean that it is not implemented somewhere.
Another real-world example, Alamofire! When calling
Alamofire.request("https://httpbin.org/get").responseJSON { response in
// what is going on here work has to be async on the main thread
}
That's why you can call it without facing any "hanging" issue on the main thread; It doesn't mean its not handled, instead it means they handle it for you so you don't have to worry about it.
Let's say I have the following code:
dispatch_async(dispatch_get_main_queue()) {
myFunction()
}
This says to call the block, which calls myFunction, asynchronously. Let's say that I call this code in my main queue, which is also the queue specified for the dispatch_async call.
When does this block actually get called in this case? Does my current queue get pre-empted and the block run immediately, or does the current call stack unroll and the block gets called at the next event loop? Or something else?
When does this block actually get called in this case? Does my current queue get pre-empted and the block run immediately, or does the current call stack unroll and the block gets called at the next event loop? Or something else?
In short, if you dispatch asynchronously to the main queue from the main queue, the dispatched block will not run until you yield back to the main run loop (and also after any other blocks dispatched to the main queue also finish).
From Grand Central Dispatch (GCD) Reference: dispatch_async
The target queue determines whether the block is invoked serially or concurrently with respect to other blocks submitted to that same queue.
From OperationQueues: Performing Tasks on the Main Thread
You can get the dispatch queue for your application’s main thread by calling the dispatch_get_main_queue function. Tasks added to this queue are performed serially on the main thread itself. Therefore, you can use this queue as a synchronization point for work being done in other parts of your application.
From these two pieces of information, we know the main queue is a serial dispatch queue and dispatch_async() will follow the rules of serial execution.
So the simple answer is the task will be run on the main queue sometime after the completion of the current context.
I couldn't find a official description of the run loop's internals, but rob mayoff a good breakdown.
Order of operations in runloop on iOS
Note that the run loop is structured so only one of these branches happens on each iteration:
Ready timers fire, or
Blocks on dispatch_get_main_queue() run, or
A single version 1 source is dispatched to its callback.
If the context is an input source or a timer fire, then the task will happen in a different iteration of the run loop. If the context is a dispatched task, then the task may actually run within the same iteration of the run loop.
I call dispatch_async(dispatch_get_main_queue()from several background threads. However, it appears that occasionally the code in the dispatch block is not executed. Could this be because i dispatch asynchronously and the thread exits before the main queue can execute the code?
Have you tried putting an NSLog in the beginning of your code snippet to be absolutely sure that it's not executing? Sometimes an if statement with faulty logic will pre-terminate your code. (From my past experience ;])
The moment the dispatch_async() call returns, it's not important whether or not the thread that invoked it subsequently exits or not - the "request is in the system" so to speak! Something else is happening in those "occasional" cases. Does your program have a run loop or call dispatch_main() at the end of its main function? Not clear whether this is a Cocoa/iOS/POSIX application you're describing.
I have weird threading issues on iOS. Consider a simple method like this:
- (BOOL)doSomething
{
[self doA];
[self doB];
}
This method should only run in context of the main thread. I need to call this method from a worker thread. I use performSelectorOnMainThread for this purpose.
If I do everything as explained here. Can a context switch happen between doA and `doB?
(I don't think so, I just want to make sure that my understanding is right here)
By "context switch" I assume you mean the main thread switching to some other main thread event (as you could always switch to another worker thread at any time).
However, main thread will finish all of doSomething before doing anything else.
Excerpt from performSelectorOnMainThread:
This method queues the message on the run loop of the main thread
using the common run loop modes—that is, the modes associated with the
NSRunLoopCommonModes constant. As part of its normal run loop
processing, the main thread dequeues the message (assuming it is
running in one of the common run loop modes) and invokes the desired
method. Multiple calls to this method from the same thread cause the
corresponding selectors to be queued and performed in the same same
order in which the calls were made.