I have this piece of code:
[[FBController sharedController] getUserDetailsWithCompletionBlock:^(NSDictionary *details)
{
// Updating UI elements
}];
I don't understand a thing: when the block is fired, the secondary thread is still running. Isn't it more correct that the completion of a block should be executed on main thread automatically?
I know that I am wrong with something and I need a couple of explanations.
The Facebook SDK documentation should give you more details, but in general a well-behaved SDK would call completion blocks on the same thread that the SDK was called from. Any long-running or asynchronous operations that the SDK may perform should operate on a separate thread, usually only visible to the SDK. Whether or not that separate thread is still running or not, is an implementation detail of the SDK - and you shouldn't care about it from the client code perspective.
You can visualise it like this:
Client Code (Main Thread) : [Request]--[Response]-[Continue Thread]-------[Completion Block]
v ^ ^
SDK Code (Main Thread) : [Immediate Operations] |
v |
SDK Code (Private Thread) : [Long Running / Asynchronous Operations]----[Finished]
In the specific example you posted, there's no 'Response' from the getUserDetailsWithCompletionBlock method, so the thread carries on as usual.
The missing piece to the jigsaw puzzle might be - "How does my completion block get executed on the main thread". Essentially this comes down to the Runloop system. Your main thread isn't actually owned and operated by your code, it's behind the scenes. There's a Main Runloop which periodically looks for things to do. When there's something to do, it operates those somethings on the main thread sequentially. When those somethings have finished, it goes back to looking for something else to do. The SDK basically adds your completion block to the main runloop, so the next time it fires, your block is there waiting to be executed.
Other things that the runloop might be doing are:
UI Updates
Delegate callbacks from UI code
Handling Timers
Touch Handling
etc... etc...
Related
This might sound quite basic and stupid but it has been bothering me for a while. How can print be classified in terms of operation - main or background ?
As a small test, on putting print in a background task - web service call :
Webservice().loadHeadlinesForSource(source: source) { headlines in
print("background print")
self.headlineViewModels = headlines.map(HeadlineViewModel.init)
DispatchQueue.main.async {
print("main thread print")
completion()
}
}
Both the print statements get printed. From previous experience, if print was a main thread task, Xcode would have given me a warning saying that I need to put that in main thread. This is an evidence that print is not a main thread operation. Note that I am not saying print is a background task.
However, I have this understanding that since print displays output on Console, it is not a background operation. As a matter of fact all logging operations are not.
How would one justify the classification ?
It seems what you consider to be a main thread operation is a call that needs to be performed on the main thread. From that perspective you are correct and have found an evidence of this call not being a main thread operation.
But does this have anything to do with anything else? Internally if needed this method may still execute its real operation on the main thread or any other thread for what we care. So in this sense a main thread operation is a restriction that call needs to be performed on main thread but has nothing to do with its execution or multithreading.
Without looking into what print does in terms of coding we can see that it works across multiple "computers". You can run your app on your device (iPhone) while plugged and Xcode on your computer will print out logs. This makes a suspicion that print is much like call to the remote server in which case the server is responsible for serializing the events so it makes no difference what thread the client is on. There are other possibilities such as dropping logs into file and then sending it which really makes little difference.
So How can print be classified in terms of operation - main or background? The answer is probably none. The call is not restricted to any thread so it is not main. It will probably lock whatever thread it is on until the operation is complete so it is not background either. Think of it like Data(contentsOf: <#T##URL#>) which will block the thread until data from given URL is retrieved (or exception is thrown).
I want to know As we all know how asynchronous task are necessary for concurrency but Wanted to know why we need the synchronous tasks. while we can achieve the same with the normal usage of function.
Thanks & regards
Rohit
When you calls something synchronously, it means that 'the thread that initiated that operation will wait for the task to finish before
continuing'. Asynchronous means that it will not wait for finish the task.
synchronous calls stops your current action and returns when the call returned. with asynchronous calls you can continue.
synchronous is the opposite of asynchronous code, and therefore is ordinary code.
At the end, if asynchronous is totally out of scope then you will not emphasize the word synchronous.
It helps to synchronise threads, as the name suggests.
consider a typical usage of GCD async and sync (pseudo)
async background_thread {
//1 call webservice or other long task that would block the main thread
sync main_thread {
//2 update UI with results from 1
}
//3 do something else that relies on 2
}
now if 2 was in an async and you needed to do something at 3 that relies on the updates at 2 to have happened, then you are not guaranteed (and most likely wont) get the behaviour you are expecting. instead, you use a sync to make sure that the task is completed before continuing the execution in the background thread.
If you are asking now, why not just take out the sync/async around 2 so it executes in order anyway? the problem is, the UI must not be updated on a background thread otherwise the behaviour is undefined (which usually means the UI lags a lot). So in essence what happens is the background thread waits at 2's sync until the main thread gets round to executing that block, then it will continue with the rest of the execution on the background thread.
If you were dealing with a task that doesnt require the main thread (or some other thread) to execute properly, then yes you may as well take out the sync at 2.
This is just one example of how a sync is useful, there are others if you are doing advanced threading in your app.
Hope this helps
Typically it's because you want to do an operation on a specific different thread but you need the result of that operation. You cannot do the operation asynchronously because your code will proceed before the operation on the other thread completes.
Apple has a very nice example:
func asset() -> AVAsset? {
var theAsset : AVAsset!
self.assetQueue.sync {
theAsset = self.getAssetInternal().copy() as! AVAsset
}
return theAsset
}
Any thread might call the asset method; but to avoid problems with shared data, we require that only functions that are executed from a particular queue (self.assetQueue) may touch an AVAsset, so when we call getAssetInternal we do it on self.assetQueue. But we also need the result returned by our call to getAssetInternal; hence the call to sync rather than async.
What is the order of operations on iOS?
I'm thinking sepcifically about timing of
setNeedsLayout and layoutSubviews
setNeedsDisplay and drawRect
touch recognition
[NSTimer scheduledTimerWithTimeInterval:0.000001 tar(...)]
dispatch_async(dispatch_get_main_queue(), ^{ /* code */}
As an example of an answer I would like to receive it could be in this format:
dispatch_async on main Happens before the next runcycle
drawRect Happens at the end of the runcycle
(Parts of this are copied from my answer to a similar question.)
It turns out that the run loop is complicated, and a simple question like “Does drawRect: happen at the end of the runcycle?” doesn't have a simple answer.
CFRunLoop is part of the open-source CoreFoundation package, so we can take a look at exactly what it entails. The run loop looks roughly like this:
while (true) {
Call kCFRunLoopBeforeTimers observer callbacks;
Call kCFRunLoopBeforeSources observer callbacks;
Perform blocks queued by CFRunLoopPerformBlock;
Call the callback of each version 0 CFRunLoopSource that has been signaled;
// Touch events are a version 0 source in iOS 8.0.
// CFSocket is a version 0 source.
if (any version 0 source callbacks were called) {
Perform blocks newly queued by CFRunLoopPerformBlock;
}
if (I didn't drain the main queue on the last iteration
AND the main queue has any blocks waiting)
{
remove all blocks from the main queue
execute all the blocks just removed from the main queue
} else {
Call kCFRunLoopBeforeWaiting observer callbacks;
// Core Animation uses a BeforeWaiting observer to perform layout and drawing.
Wait for a CFRunLoopSource to be signalled
OR for a timer to fire
OR for a block to be added to the main queue;
Call kCFRunLoopAfterWaiting observer callbacks;
if (the event was a timer) {
call CFRunLoopTimer callbacks for timers that should have fired by now
} else if (event was a block arriving on the main queue) {
remove all blocks from the main queue
execute all the blocks just removed from the main queue
} else {
look up the version 1 CFRunLoopSource for the event
if (I found a version 1 source) {
call the source's callback
}
// Interface orientation changes are a version 1 source in iOS 8.0.
}
}
Perform blocks queued by CFRunLoopPerformBlock;
}
Core Animation registers a kCFRunLoopBeforeWaiting observer with an order of 2000000 (although that is not documented; you can figure it out by printing [NSRunLoop mainRunLoop].description). This observer commits the current CATransaction, which (if necessary) performs layout (updateConstraints and layoutSubviews) and then drawing (drawRect:).
Note that the run loop can evaluate the true in while(true) twice before executing BeforeWaiting observers. If it dispatches timers or a version 1 source, and that puts block on the main queue, the run loop will go around twice before calling the BeforeWaiting observers (and it will dispatch version 0 sources both times).
The system uses a mixture of version 0 sources and version 1 sources. In my testing, touch events are delivered using a version 0 source. (You can tell by putting a breakpoint in a touch handler; the stack trace contains __CFRunLoopDoSources0.) Events like entering/leaving foreground are dispatched through CFRunLoopPerformBlock, so I don't know what kind of source really provides them. Interface orientation changes are delivered through a version 1 source. CFSocket is documented to be a version 0 source. (It's likely that NSURLSession and NSURLConnection use CFSocket internally.)
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.
After that, any number of version 0 sources can call their callbacks.
So:
Layout always happens before drawing, if both are pending when the Core Animation observer runs. The CA observer runs after timers, main queue blocks, or the external event callback have run.
The main GCD queue has seniority over timers and version 1 sources, if the run loop didn't drain the main queue on the prior turn of the loop.
Timers have seniority over the main queue and version 1 sources, should all three be ready.
The main queue has seniority over version 1 sources, should both be ready.
Also remember that you can request immediate layout at any time using layoutIfNeeded.
One task after the other is added to the runloop from various sources; the runloop will execute the oldest task on the runloop and not start another task until the call for that task returns.
Handling of user interaction
UI Components call setNeedsLayout and setNeedsDisplay if they need an update
Layouting is done using layoutSubviews (called indirectly by layoutSublayers)
Painting is done using drawRect and drawInContext:
dispatch_async call is performed
Your timer with 0.000001 seconds delay could be executed before or after the dispatch_async. Difficult to say.
1 and 2 are actually mixed because it's mostly the user interaction causing changes in the UI by calling setNeedsLayout and setNeedsDisplay somewhere.
The order of 1, 2, 3 and 4 is well-defined. 5 should also always happen afterwards. NSTimer depends on various circumstances - you should not rely that it's called before or after the dispatch_async call but it most likely will be executed after the painting is done.
As mentioned in title, I would like to open UIManagedDocument synchronously, i.e, I would like my execution to wait till open completes. I'm opening document on mainThread only.
Current API to open uses block
[UIManagedDocument openWithCompletionHandler:(void (^)(BOOL success))];
Locks usage mentioned at link works well on threads other than main thread. If I use locks on mainThread, it freezes execution of app.
Any advice would be helpful. Thanks.
First, let me say that I strongly discourage doing this. Your main thread just waits, and does nothing while waiting for the call to complete. Under certain circumstances, the system will kill your app if it does not respond on the main thread. This is highly unusual.
I guess you should be the one to decide when/how you should use various programming tools.
This one does exactly what you want... block the main thread until the completion handler runs. Again, I do not recommend doing this, but hey, it's a tool, and I'll take the NRA stance: guns don't kill people...
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
usleep(USEC_PER_SEC/10);
}
Another option is to execute the run loop. However, this isn't really synchronous, because the run loop will actually process other events. I've used this technique in some unit tests. It is similar to the above, but still allows other stuff to happen on the main thread (for example, the completion handler may invoke an operation on the main queue, which may not get executed in the previous method).
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:futureTime];
}
There are other methods as well, but these are simple, easy to understand, and stick out like a sore thumb so it's easy to know you are doing something unorthodox.
I should also note that I've never encountered a good reason to do this in anything other than tests. You can deadlock your code, and not returning from the main run loop is a slippery slope (even if you are manually executing it yourself - note that what called you is still waiting and running the loop again could re-enter that code, or cause some other issue).
Asynchronous APIs are GREAT. The condition variable approach or using barriers for concurrent queues are reasonable ways to synchronize when using other threads. Synchronizing the main thread is the opposite of what you should be doing.
Good luck... and make sure you register your guns, and always carry your concealed weapons permit. This is certainly the wild west. There's always a John Wesley Harden out there looking for a gun fight.
I have a TCP connection that is open continuously for communication with an external device. There is a lot going on in the communication pipe which causes the UI to become unresponsive at times.
I would like to put the communication on a separate thread. I understand detachNewThread and how it calls a #selector. My issue is that I am not sure how this would be used in conjunction with something like NSStream?
Rather than manually creating a thread and managing thread safety issues, you might prefer to use Grand Central Dispatch ('GCD'). That allows you to post blocks — which are packets of code and some state — off to be executed away from the main thread and wherever the OS thinks is most appropriate. If you create a serial dispatch queue you can even be certain that if you post a new block while an old one has yet to finish, the system will wait until it finishes.
E.g.
// you'd want to make this an instance variable in a real program
dispatch_queue_t serialDispatchQueue =
dispatch_queue_create(
"A handy label for debugging",
DISPATCH_QUEUE_SERIAL);
...
dispatch_async(serialDispatchQueue,
^{
NSLog(#"all code in here occurs on the dispatch queue ...");
});
/* lots of other things here */
dispatch_async(serialDispatchQueue,
^{
NSLog(#"... and this won't happen until after everything already dispatched");
});
...
// cleanup, for when you're done
dispatch_release(serialDispatchQueue);
A very quick introduction to GCD is here, Apple's more thorough introduction is also worth reading.