Which thread to call CFRunLoopStop(CFRunLoopGetCurrent())? - ios

I'm running CFRunLoopRun() in Thread A. To terminate the run loop, should I come back to Thread A to call CFRunLoopStop(CFRunLoopGetCurrent())?
What happen if I call CFRunLoopStop(CFRunLoopGetCurrent()) in Thread B? If I'm in Thread B, how could I come back to Thread A to perform this call?
Sorry for this basic question. I just switched from Android to iOS and face a lot of context switch...
Thanks!

If you are using POSIX threads, then you should definitely follow the link provided in the comment by #Robotic Cat. It points to a document that describes adding a source to the CFRunLoop that can be triggered to stop the run loop.
If you are using NSThread subclasses, and you have a handle to the one you want to stop, you should be able to create a method on that NSThread subclass that stops the CFRunLoop with the code you noted above and invoke it with performSelector:onThread:withObject:waitUntilDone:.

Related

Clear process flow of NSRunLoop

Digging more than one day....Apple, Google, Slideshare and stackoverflow. But still not clear about NSRunLoop.
Every thread has a runloop by default.Application mainThread has mainRunLoop.
1. If MainRunLoop get input events is it creating new thread to execute it? Then another runLoop created? How then multiple thread and multiple runLoop work? Communicate?
2. If runLoop has no input event/task it sleeps.When a RunLoop ends?
3. Why i should care about runLoop?
4. Where i can use it?
Where i miss that i can't understand the life cycle?
Lets look on your`s list:
Wrong. Threads do not have built-in runloop. They need to be created manually.
Runloop doesn`t create another threads, its immediately executes an event. That is why at the main thread we can see locked interface - by heavy-load tasks in the main thread (UI in iPhone runs on the main thread). Runloops can communicate with each other with the help of mac ports.
Runloop sleeps before the first event come, then wakes up and ends. Only exception - timer, but it will not runloop. Runloop need to start run every time after Event (in the loop). If you call the run, there is already a built-in loop.
Can use to create some threads which must track or execute something periodically. For example, you can create a thread, when runloop for it and then other threads can execute it`s selectors through performSelector. This creates a background query processor, which does not require each time to create a new thread.

Why are UI events not thread-safe in Swift/Objective-C?

So I'm beginning to learn the basics of Grand Central Dispatch and the whole concept of multithreading with iOS applications. Every tutorial will tell you that you must run UI events on the main thread, but I don't completely understand why.
Here's a problem I came across yesterday, and finally fixed it by running a segue on the main thread, but I still don't understand why running it off the main thread was a problem:
I had a custom initial VC (barcode scanner) and a segue to a new view controller with a UIWebView attached. As soon as the VC found a barcode, it called a handler, and in that closure, I had a performSegueWithIdentifier. However, I got a EXC_BAD_ACCESS because of this (it didn't happen when the second VC had a label or a UIImageView, just with UIWebView). I finally realized that for some reason, the closure was called off the main thread, and thus the segue was being performed off the main thread. Why exactly would performing the segue on another thread throw a memory error? Is it because self in self.performSegueWithIdentifier was somehow nil? And why wouldn't Swift automatically dispatch a segue event on the main thread?
Interesting question! The crash isn't related to UIKit. It's a crash specific to UIWebView. Looking at the stack trace, the exception happens in the WebCore::FloatingPointEnvironment::saveMainThreadEnvironment function, which is part of the WebKit init process. Since WebKit manages a threaded execution environment of its own, it makes sense that it needs a definite starting point (i.e. the main thread) to build this environment.
UIKit operations (like presenting a view controller) performed on threads other than main will not cause an exception, but they will be delayed (depending on the QoS of the dispatching queue).
As for why the UIKit operations aren't automatically dispatched on the main queue, I can only speculate that adding extra checks inside the library calls would add too much redundant work that can be avoided simply by following a convention.
For a larger discussion on UIKit and the main thread, see this answer: Why must UIKit operations be performed on the main thread?
The short answer is that all operations that modify the UI of your app need to come together in one place to be evaluated to generate the next frame at regular intervals (the V-Sync interval specifically). Keeping track of all of the mutated state requires all changes to happen synchronously, and for performance reasons, all of these operations are generally batched up and executed once per frame (while also coordinating with the GPU).
Making things thread-safe is difficult, and has major performance implications, all of which can be avoided by requiring access to come from a single (main) thread. You want your UI frameworks to be as fast (i.e. responsive) as possible. If you declare that all your UI objects are main-thread only, then you don't have to slow them down with a bunch of synchronization overhead. I've heard it asked, 'if UIKit is really main-thread only, then why don't they just check the current thread and abort() if it's not the main thread?' and the answer is the same: Even a simple check like that would result in an appreciable performance hit given the number of methods that would need the check and the frequency with which they're called. It's all about speed.
Also, remember, not too long ago, all applications were single threaded.

inner working of asynchronous block in iOS program?

I am using the following method to browse the photos library in iPhone:
enumerateGroupsWithTypes:usingBlock:failureBlock:
From the API doc and my test, I know the block runs asynchronously. However, my question is: how exactly this block runs asynchronously?
I.e. does it run via the same runloop as the main thread? or via a new & different runloop?
also, does it run in a new & different thread? (assuming 'thread' is not same as 'runloop')
Let's say that I want to do something to update the view(UI) inside the block, particularly do a :
[collectionView reloadData].
How will this "reloadData" message be handled? Will it be handled in the same runloop as the block itself? [Update question: will this "reloadData" be asynchronous or synchronous relative to this block's execution?]
And at last, in case I am asking dumb questions, can anyone suggest a book or other pointers to understand the inner working of asynchronous block in iOS program, e.g. how it's related to runloops and threads?
thanks.
the block is called on the main queue (running on the main thread)
no special runloop mode or so is entered ...
you can see it when you write a simple demo app
either the ALAssetFramework uses GCD dispatch or it registers as a source for runloop events.. but thats an implementation detail
about the update:
a block is a little like a regular function... so reloadData is synchronous normally and it will remain synchronous when used in a block therefore

How do i schedule something in the runloop of another thread?

I am writing an application that is going to send/receive data over tcp connections and I wanted to schedule the read/write to happen in the run loop of a different thread. Meaning Thread 1 is creating the connection and scheduling it on the run loop of Thread 2. I am unable to find any way of accessing the run loop of a different thread so I wrote a piece of code that the secondary thread will run which will store its run loop in a globally accessible location. I wanted to know if this is the right way to do it or if there is any other/better way to do the same and also if the way I have done it will cause problems like access to the run loop not being thread safe and causing issues if i attempt to schedule multiple things on the run loop of the same thread from multiple threads.
Something like the following.
[NSRunLoop currentRunLoop] --> This I can do from the thread whose runloop I want to access
NSRunLoop * secondthreadrunloop = [secondthread getRunLoop]; -->But is there anything like this?
I encountered the same problem recently and it seems that the answer is - no, you cannot schedule anything on a NSRunLoop running on a different thread. Apple says that NSRunLoop is not thread safe which means that attaching an NSTimer instance to it would result in an undefined behaviour (I have checked it, in my case it randomly generates crashes).
What can be done though is to schedule a repeating timer from the background thread itself and make it pick up the work you want it to do from some atomic property.

NSOperation using GCD, ensure all on the same thread

I have a 'concurrent' NSOperation, and during it's work it uses some controller classes that internally use GCD. When these controller classes return with their completion block, the completion block is on another thread.
I know I could store the current thread in the operation start method and run performSelectorOnThread:, but ideally I would like to wrap the completion in a GCD block and dispatch onto the same thread as the operation started on. Is this even possible with GCD, as I can only specify a queue to dispatch to.
What's the best way to bring this work back onto the same thread that the operation started on? Apart from what I already suggested... unless this is the best way.
When the operation is completed the UI update or any other related things has to be done on main thread. The following link might be useful to you about CGD.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
I don't think this is really possible/advisable. Since iOS 4 onwards, NSOperation is using GCD , and as GCD is managing my threads - I don't think I should be keeping references to them.
I did find some util methods for executing blocks of code on a particular thread. See Practical Blocks by Mike Ash or this article doing similar thing.
As my goal was to keep my core data calls on the same thread, instead I opted to upgrade my code to use parent/child managed object contexts with NSPrivateQueueConcurrencyType, and then used performBlock: on the managed object context to ensure all my call backs on the separate threads got executed correctly by core data.

Resources