Will the system send an NSWillBecomeMultiThreadedNotification when I create POSIX threads? - iphone

I tried it, but I think this notification isn't coming. Is that the normal case?

No, this notification is sent by NSThread. If you're using ordinary pthreads, it won't be sent.

From the docs:
Protecting the Cocoa Frameworks For
multithreaded applications, Cocoa
frameworks use locks and other forms
of internal synchronization to ensure
they behave correctly. To prevent
these locks from degrading performance
in the single-threaded case, however,
Cocoa does not create them until the
application spawns its first new
thread using the NSThread class. If
you spawn threads using only POSIX
thread routines, Cocoa does not
receive the notifications it needs to
know that your application is now
multithreaded. When that happens,
operations involving the Cocoa
frameworks may destabilize or crash
your application.
To let Cocoa know that you intend to
use multiple threads, all you have to
do is spawn a single thread using the
NSThread class and let that thread
immediately exit. Your thread entry
point need not do anything. Just the
act of spawning a thread using
NSThread is enough to ensure that the
locks needed by the Cocoa frameworks
are put in place.
If you are not sure if Cocoa thinks
your application is multithreaded or
not, you can use the isMultiThreaded
method of NSThread to check.

It should also be noted that 'times have changed' since NSWillBecomeMultiThreadedNotification was added to Foundation. Multi-threaded programming is now much, much more common. It's now entirely within the realm of possibility, even likely, that you'll never see this notification posted in an app. Modern apps become multi-threaded very early in their life, possibly before any part of your code is ever executed. Also from the documentation:
If you are developing a Cocoa library,
you can register as an observer for
the
NSWillBecomeMultiThreadedNotification
if you want to be notified when the
application becomes multithreaded. You
should not rely on receiving this
notification, though, as it might be
dispatched before your library code is
ever called.
I'd use [NSThread isMultiThreaded] instead of relying on NSWillBecomeMultiThreadedNotification.

Related

How to find and cancel background Thread in Swift

I am calling a monitoring task via thread using the following code which is called from the viewDidLoad() in a ViewController:
let myDaemon = Thread(target: self.myMonitor, selector:#selector(self.myMonitor), object: nil)
myDaemon.start()
I have been unable to find a way to find and cancel that thread without closing the app. Is there maybe an alternate way to launch the thread so I can cancel it if needed?
I thought about creating an observer so I could cancel it from another VC but since the Daemon is initialized in the viewDidLoad, I can't access it outside of that block.
I'm using Swift 5. Any suggestions are appreciated.
Thanks,
First, you should almost never use Thread in Swift. Directly accessing threads has been discouraged in Cocoa since longer than Swift has been a language. You should generally be using, in order of preference for the kinds of problems threads are usually used for, async/await (possibly plus an AsyncChannel), OperationQueues, or DispatchQueues. That said, it's a fine question, and there are still very rare cases where a Thread would be appropriate, or at least useful.
To cancel a thread, you will either need to keep track of it (the returned value) so you can call .cancel(), or you need to have a way to communicate with the thread (a Pipe for example) so that you can send a custom "stop" message. That means storing that returned value (or the communication mechanism) somewhere outside the VC.
A ViewController should not own a global object like a Thread. ViewControllers come and go. You should move your thread management (if you're going to do thread management, which you generally shouldn't) into a model object that the VCs share.
Note that canceling a thread does not cause a thread to stop running. The only thing it does is set the isCancelled flag. If is still up to your thread to periodically check itself for cancellation and stop. (You may already know this, but it's a very common confusion, so I want to make sure anyone reading this later is aware.)
There is no list of all existing threads for you to search (and that would be pretty obnoxious since the frameworks generate quite a lot of threads you would need to crawl through). If you want to keep track of a thread, you need to store it somewhere.

Is it sensible to start `CLLocationManager` on a background thread?

According to the documentation of CLLocationManagerDelegate
The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread.
I am not clear as to whether this means that to receive location manager updates on a background thread, we must instantiate the location manager on that background thread or simply call the startUpdatingLocation() method on that thread.
In any event, this explains an issue when a CLLocationManagerDelegate does not receive any events from a CLLocationManager which was started on a background thread:
That thread must itself have an active run loop
If I understand run loop functioning correctly, all NSThreads are instantiated with a run loop, but the run loop will only be running if you assign some work to the thread. Therefore, to have a CLLocationManager send events correctly on a background thread, we need to set the thread's run loop to loop permanently so that it can process the CLLocationManager's calls as they arrive.
A reasonable solution to making sure the run loop is running is suggested in this question but the author implies that this is a processor expensive way of doing it.
Also, according to the threading documentation,
Threading has a real cost to your program (and the system) in terms of memory use and performance
I appreciate that we are all using lots of threading anyway, by using Grand Central Dispatch, but Grand Central Dispatch probably mitigates a lot of this in its internal thread management.
So my first question is, is it worthwhile setting up a background thread with a continuously running run loop, in order to have location events dealt with on a background thread, or will this involve an unreasonable extra amount of processing when compared to leaving the manager on the main thread?
Secondly, if it is worthwhile, is there a good way to do this using Grand Central Dispatch. As I understand the documentation, Grand Central Dispatch manages its own threads and we have no means of knowing which thread a given block will be executed on. I presume we could simply execute the usual run loop code to make the run loop of whichever thread our CLLocationManager instantiation is run on loop continuously, but might this not then affect other tasks independently assigned to Grand Central Dispatch?
This is a somewhat opinion-based question, but I have a pretty strong opinion on it :D
No.
Just deliver the events to the main queue, and dispatch any work to a background queue if it's non-trivial. Anything else is a lot of complexity for little benefit. CLLocationManager pre-dates GCD, so this was useful information in the days when we occasionally managed run loops by hand and dispatching from one thread to another was a pain. GCD gets rid of most of that, and is absolutely the tool you should use for this. Just let GCD handle it with dispatch_async.
You absolutely should not set up your own NSThread for this kind of thing. They're still necessary at times for interacting with C++, but generally if GCD can handle something, you should let it, and avoid NSThread as much as possible.

Implementing multithread using XCode for IPhone

Is there a way implement multi threading in IPhone using xcode? Could you refer me to few tuts that I could use.
Thanks and Regards
Abishek R Srikaanth
The easiest way to implement multi-threading is probably going to be using NSOperationQueue. You subclass NSOperation, or create an NSBlockOperation with the code block you want to run in the background. Set a completion block if you need to be notified on the main thread when the background task finishes. Then add your operation to an NSOperationQueue and you're set! You can also set dependancies on the operation to run a series of events one at a time, or add many operations to the queue if you don't care what order they're executed in.
There are other ways of doing threading, but NSOperation is especially nice since it wraps everything up into a neat unit of work, where you're less likely to make shared memory mistakes, and also you can trust NSOperationQueue to look at the number of cores in your device and do the right thing when it comes to running many operations at once.

Running C code in an Objective C (Cocoa) Thread (for iOS)

First of all, I am a a very new Objective C/Cocoa iOS Developer but I've written C/C++ applications before.
So I managed to run the Rabbitmq-c (http://hg.rabbitmq.com/rabbitmq-c/) client inside my iPhone App, and I can connect to Rabbitmq directly from my app and even consume a queue item. So all's good.
Now my problem is, my iPhone app needs to use the rabbitmq-c library to poll for incoming messages in from the server. Probably there will be, an almost infinite while loop.
Do I have to take this to a new thread? Ideally, I want to wrap the rabbitmq-c class as an Async objective C class and use NSNotification (or something similar) to notify my UI. I'm a bit leery of creating a new thread, as I read about stuffs like Runloop etc can solve a lot of problems without using an extra thread.
What is the best way for me to go about this? Any examples of code or directions would be helpful. Please remember, I am not dealing with an Objective C code/Coca rabbitmq library here, I'm using C code inside my iPhone app.
Thanks
Subrat
don't block the main thread with your server polling.
since the operation never ends, create your own thread and run loop for this server polling. you can potentially use the run loop (each thread has one) instead of the infinite while. the alternatives involve regularly spawning threads. it's easiest to just use one thread for this.
once you have an update, post the notification (if you choose NSNotification) from the main thread -- UIKit is meant to operate from the main thread only.
for samples, i'd begin with samples related to NSRunLoop and CFRunLoop.
good luck
You can also create custom delegates for updating the UI, or the stuff related to UIKit.
Notifications might be a little easier to code and offer the advantage that multiple objects can observe one notification. With delegates, such a thing cannot be done without modifying the delegating object (and is unusual).
Some advantages of delegating:
The connection between delegating object and delegate is made clearer, especially if implementing the delegate is mandatory.
If more than one type of message has to be passed from delegatee to delegate, delegating can make this clearer by specifying one delegate method per message.
Or other way is to write method to receive messages. This method can have infinite loop.
Later you can put this method in background thread like this.
[self performSelectorInBackground:#selector(receiveMessages) withObject:nil];

KVO rocks. Now how do I use it asynchronously?

I am sold on KVO but if used in the obvious way it is synchronous. I would like to use it in a situation where I am firing off many KVO messages in rapid succession and it is causing my app to grind to a halt as the KVO messages are handled. Can someone suggest an approach - perhaps using NSOperation or NSThread - that will work here?
My goal is to retain the decoupled, flexibility of KVO if possible.
KVO is inherently single threaded in that the KVO notifications will be delivered on the same thread as the change.
Of course, UIKit and Cocoa both really only want you to be diddling UI elements on the main thread.
Thus, if you are doing asynchronous operations, you are most likely using threads and, if so, already have a synchronization issue in that you need to get the notifs from some thread to the main thread.
And therein lies the key. Instead of blindly forwarding each change notification as it comes in, you can coalesce the change notifications before passing them on to the main thread.
There are a variety of means via which you can do this. The specific solution is going to be quite unique to your application, most likely.
Personally, I try to avoid coalesce-and-forward of fine grained operations. I find it far simpler to tell the main thread that a particular sub-graph of objects have changed. More likely than not, the drawing code that will then make the changes visible to the user is going to need to redraw related state and, thus, related changes will be automatically reflected.
The key, as you have surmised, is to throttle the notifications so you don't bog down app responsiveness (or destroy the devices battery life).
Use the Receptionist Pattern as recommended by Apple https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/ReceptionistPattern/ReceptionistPattern.html
Check out NSNotification. It's not quite the same thing, but you can fire off notifications on background threads (with a little bit of research and work). You can maintain the nice decoupling and fire-and-forget behavior.