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.
Related
I tried running the following code and it raises the following error every time:
DispatchQueue.main.sync { }
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
I found this post on stackoverflow that says to never run synchronous code on the main queue:
DispatchQueue crashing with main.sync in Swift
I had assumed that because the sync { } method is there that means there is some context that it can be used. Is there absolutely no use for executing synchronous code on the main queue?
I had assumed that because the sync { } method is there that means there is some context that it can be used.
Yes, it's there to be used when appropriate, but that doesn't mean it should be applied to the main queue.
Is there absolutely no use for executing synchronous code on the main
queue?
The sync command blocks and waits for its operation to be performed and completed on the specified queue. That queue can certainly be the main queue. But the queue that blocks cannot be the main queue! You must never say sync when you are on the main queue, as you will then be blocking the main queue which is illegal; and you must really never say DispatchQueue.main.sync when you are on the main queue, as you will be blocking the main queue forever (thereby causing the heat death of the universe).
Really the best thing to do is adopt async/await and never mention DispatchQueue again. All these concerns vanish in a puff of smoke and your code becomes safe and easy to reason about, automatically.
sync should not be used in the main queue because you are likely to block everything, the method is there for "custom" queues (for example you created a queue and YOU handle when it has to be blocked and unblocked) the main queue is a special case, and since it is not manage by you introducing a block may generate unexpected behavior (that usually translates into a crash)
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.
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.
I'm learning about blocks from a Stanford video. I'm now at the part which explains core data. The teachers mentions something about:
- (void)openWithCompletionHandler:(void (^)(BOOL success))completionHandler;
He said that completionhandler block will be called in the thread which called the method. So basically the method runs async but the blocks get called on the thread, lets assume main.
So my question is do all blocks run on the thread from where the method call was made. To illustrate why I ask this question, I have a Async class which does request to a server.
The format of all these methods is like this:
- (void) getSomething:(id <delegateWhatever> const)delegate{
goto background thread using GCD..
Got result from server...
Go back to main thread and call the delegate method...
}
When I use blocks I do not need to worry about going back to main thread if they will be called where the call was made?
Hope this is clear,
Thanks in advance
If something runs asynchronously, you should read a documentation to know on which thread, e.g. the completion block will be executed. If it is your code, you are in charge here, you can use global GCD queues, you can create your own queue and execute it there or whatever...
In general, blocks behaves like a function or a method call, it is executed on thread, which calls it. It is even possible that the same block will be executed from 2 different threads at the same time.
And just to be clear: Even if you are using blocks, you need to care about going back to main thread, of course if it is necessary
Nothing forces blocks to be called on a particular thread, so it depends on the specific method whether or not you need to worry about its callback being on the main thread. (In practice I don't remember ever seeing a library where a method called on the main thread would not call its completion handler also on the main thread. But you still need to read the documentation of the specific library and method you are using, as always.)
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.