Is there a way that I can execute a block rather than a selector corresponding to this and similar methods?
I have observers that may receive events that aren't generated on the main thread. I want the action to be performed on the main thread if it is primarily UI oriented. Right now, I need to write two methods to do this, where one is the event observer, and the second is the code that needs to be executed on the main thread.
I would like to encapsulate this all into one method, if I could.
GCD should do the trick:
dispatch_sync(dispatch_get_main_queue(), ^{
// Do stuff here
});
Or dispatch_async if you were planning on waitUntilDone:NO. The main queue is guaranteed to be running on the main thread, so it is safe for UI operations.
The preferable technology for block-supporting multhreading actions is called Grand Central Dispatch. You can find some sample code on Wikipedia and in the Grand Central Dispatch (GCD) Reference
dispatch_async(backgroundQueue, ^{
//background tasks
dispatch_async(dispatch_get_main_queue(), ^{
//tasks on main thread
});
});
Related
Im trying to convert the following to objective-c code.
This is the current thread I have in C and works fine
//calling EnrollThread method on a thread in C
pthread_t thread_id;
pthread_create( &thread_id, NULL, EnrollThread, pParams );
//What the EnrollThread method structure looks like in C
void* EnrollThread( void *arg )
What my method structure looks like now that I've changed it to objective-c
-(void)enrollThreadWithParams:(LPBIOPERPARAMS)params;
Now I'm not sure how to call this objective-c method with the pthread_create call.
I've tried something like this:
pthread_create( &thread_id, NULL, [refToSelf enrollThreadWithParams:pParams], pParams );
But I believe I have it wrong. Can anyone enlighten me on why this does not work and what it is I need to do to fix it so that I can create my thread in the background? My UI is getting locked until the method finishes what it's doing.
I was thinking of also using dispatch_sync but I haven't tried that.
In objective C you don't really use pthread_create, although you can still use it, but the thread entry point needs to be a C function, so I'm not sure if this would be the best approach.
There are many options, as you can read in the Threading and Concurrency documents.
performSelectorInBackground method of NSObject (and subclasses)
dispatch_async (not dispatch_sync as you mentioned)
NSOperation and NSOperationQueue
NSThread class
I would suggest giving it a shot to the first one, since it is the easiest, and very straightforward, also the second one is very easy because you don't have to create external objects, you just place inline the code to be executed in parallel.
The go to reference for concurrent programming is the Concurrency Programming Guide which walks you through dispatch queues (known as Grand Central Dispatch, GCD) and operation queues. Both are incredibly easy to use and offer their own respective advantages.
In their simplest forms, both of these are pretty easy to use. As others have pointed out, the process for creating a dispatch queue and then dispatching something to that queue is:
dispatch_queue_t queue = dispatch_queue_create("com.domain.app", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// something to do in the background
});
The operation queue equivalent is:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// something to do in the background
}];
Personally, I prefer operation queues where:
I need controlled/limited concurrency (i.e. I'm going to dispatch a bunch of things to that queue and I want them to run concurrent with respect to not only the main queue, but also with respect to each other, but I don't want more than a few of those running simultaneously). A good example would be when doing concurrent network requests, where you want them running concurrently (because you get huge performance benefit) but you generally don't want more than four of them running at any given time). With an operation queue, one can specify maxConcurrentOperationCount whereas this tougher to do with GCD.
I need fine level of control over dependencies. For example, I'm going to start operations A, B, C, D, and E, but B is dependent on A (i.e. B shouldn't start before A finishes), D is dependent upon C, and E is dependent upon both B and D finishing.
I need to enjoy concurrency on tasks that, themselves, run asynchronously. Operations offer a fine degree of control over what determines when the operation is to be declared as isFinished with the use of NSOperation subclass that uses "concurrent operations". A common example is the network operation which, if you use the delegate-based implementation, runs asynchronously, but you still want to use operations to control the flow of one to the next. The very nice networking library, AFNetworking, for example, uses operations extensively, for this reason.
On the other hand, GCD is great for simple one-off asynchronous tasks (because you can avail yourself of built-in "global queues", freeing yourself from making your own queue), serial queues for synchronizing access to some shared resource, dispatch sources like timers, signaling between threads with semaphores, etc. GCD is generally where people get started with concurrent programming in Cocoa and Cocoa Touch.
Bottom line, I personally use operation queues for application-level asynchronous operations (network queues, image processing queues, etc.), where the degree of concurrency becomes and important issue). I tend to use GCD for lower-level stuff or quick and simple stuff. GCD (with dispatch_async) is a great place to start as you dip your toe into the ocean of concurrent programming, so go for it.
There are two things I'd encourage you to be aware of, regardless of which of these two technologies you use:
First, remember that (in iOS at least) you always want to do user interface tasks on the main queue. So the common patterns are:
dispatch_async(queue, ^{
// do something slow here
// when done, update the UI and model objects on the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// UI and model updates can go here
});
});
or
[queue addOperationWithBlock:^{
// do something slow here
// when done, update the UI and model objects on the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// do UI and model updates here
}];
}];
The other important issue to consider is synchronization and "thread-safety". (See the Synchronization section of the Threading Programming Guide.) You want to make sure that you don't, for example, have the main thread populating some table view while, at the same time, some background queue is changing the data used by that table view at the same time. You want to make sure that while any given thread is using some model object or other shared resource, that another thread isn't mutating it, leaving it in some inconsistent state.
There's too much to cover in the world of concurrent programming. The WWDC videos (including 2011 and 2012) offer some great background on GCD and asynchronous programming patterns, so make sure you avail yourself of that great resource.
If you already have working code, there is no reason to abandon pthreads. You should be able to use it just fine.
If, however, you want an alternative, but you want to keep your existing pthread entry point, you can do this easily enough...
dispatch_queue_t queue = dispatch_queue_create("EnrollThread", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
EnrollThread(parms);
});
I'm trying to understand Operations and Threads better, and looked to AFNetworking's AFURLConnectionOperation subclass for example, real-world, source code.
My current understanding is when instances of NSOperation are added to an operation queue, the queue, among other things, manages the thread responsible for executing the operation. In Apple's documentation of NSOperation it points out that even if subclasses return YES for -isConcurrent the operation will always be started on a separate thread (as of 10.6).
Based on Apple's strong language throughout the Thread Programming Guide and Concurrency Programming Guide, it seems like managing a thread is best left up to the internal implementation of NSOperationQueue.
However, AFNetworking's AFURLConnectionOperation subclass spawns a new NSThread, and the execution of the operation's -main method is pushed off onto this network request thread. Why? Why is this network request thread necessary? Is this a defensive programming technique because the library is designed to be used by a wide audience? Is it just less hassle for consumers of the library to debug? Is there a (subtle) performance benefit to having all networking activity on a dedicated thread?
(Added Jan 26th)
In a blog post by Dave Dribin, he illustrates how to move an operation back onto the main thread using the specific example of NSURLConnection.
My curiosity comes from the following section in Apple's Thread Programming Guide:
Keep Your Threads Reasonably Busy.
If you decide to create and
manage threads manually, remember that threads consume precious system
resources. You should do your best to make sure that any tasks you
assign to threads are reasonably long-lived and productive. At the
same time, you should not be afraid to terminate threads that are
spending most of their time idle. Threads use a nontrivial amount of
memory, some of it wired, so releasing an idle thread not only helps
reduce your application’s memory footprint, it also frees up more
physical memory for other system processes to use.
It seems to me that AFNetworking's network request thread isn't being "kept reasonably busy;" it's running an infinite while-loop for handling networking I/O. But, see, that's the point of this questions - I don't know and I am only guessing.
Any insight or deconstruction of AFURLConnectionOperation with specific regards to operations, threads (run loops?), and / or GCD would be highly beneficial to filling in the gaps of my understanding.
Its an interesting question and the answer is all about the semantics of how NSOperation and NSURLConnection interact and work together.
An NSURLConnection is itself an asynchronous task. It all happens in the background and calls its delegate periodically with the results. When you start an NSURLConnection it schedules the delegate callbacks using the runloop it is scheduled on, so a runloop must always be running on the thread you are executing an NSURLConnection on.
Therefore the method -start on our AFURLConnectionOperation will always have to return before the operation finishes so it can receive the callbacks. This requires that AFURLConnectionOperation be an asynchronous operation.
from: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/index.html
The value of property is YES for operations that run asynchronously with respect to the current thread or NO for operations that run synchronously on the current thread. The default value of this property is NO.
But AFURLConnectionOperation overrides this method and returns YES as we would expect. Then we see from the class description:
When you call the start method of an asynchronous operation, that method may return before the corresponding task is completed. An asynchronous operation object is responsible for scheduling its task on a separate thread. The operation could do that by starting a new thread directly, by calling an asynchronous method, or by submitting a block to a dispatch queue for execution. It does not actually matter if the operation is ongoing when control returns to the caller, only that it could be ongoing.
AFNetworking creates a single network thread using a class method that it schedules all the NSURLConnection objects (and their resulting delegate callbacks) on. Here is that code from AFURLConnectionOperation
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
#autoreleasepool {
[[NSThread currentThread] setName:#"AFNetworking"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
+ (NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:#selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});
return _networkRequestThread;
}
Here is code from AFURLConnectionOperation showing them scheduling the NSURLConnection on the runloop of the AFNetwokring thread in all runloop modes
- (void)start {
[self.lock lock];
if ([self isCancelled]) {
[self performSelector:#selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
} else if ([self isReady]) {
self.state = AFOperationExecutingState;
[self performSelector:#selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
[self.lock unlock];
}
- (void)operationDidStart {
[self.lock lock];
if (![self isCancelled]) {
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
for (NSString *runLoopMode in self.runLoopModes) {
[self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
}
//...
}
[self.lock unlock];
}
here [NSRunloop currentRunloop] retrieves the runloop on the AFNetworking thread instead of the mainRunloop as the -operationDidStart method is called from that thread. As a bonus we get to run the outputStream on the background thread's runloop as well.
Now AFURLConnectionOperation waits for the NSURLConnection callbacks and updates its own NSOperation state variables (cancelled, finished, executing) itself as the network request progresses. The AFNetworking thread spins its runloop repeatedly so that as NSURLConnections from potentially many AFURLConnectionOperations schedule their callbacks they are called and the AFURLConnectionOperation objects can react to them.
If you always plan to use queues to execute your operations, it is simpler to define them as synchronous. If you execute operations manually, though, you might want to define your operation objects as asynchronous. Defining an asynchronous operation requires more work, because you have to monitor the ongoing state of your task and report changes in that state using KVO notifications. But defining asynchronous operations is useful in cases where you want to ensure that a manually executed operation does not block the calling thread.
Also note that you can also use an NSOperation without a NSOperationQueue by calling -start and observing it until -isFinished returns YES. If AFURLConnectionOperation was implemented as a synchronous operation and blocked the current thread waiting for NSURLConnection to finish it would never actually finish as NSURLConnection would schedule its callbacks on the current runloop, which wouldn't be running as we would be blocking it. Therefore to support this valid scenario of using NSOperation we have to make the AFURLConnectionOperation asynchronous.
Answers to Questions
Yes, AFNetworking creates one thread which it uses to schedule all connections. Thread creation is expensive. (this is partly why GCD was created. GCD keeps a pool of threads running for you and dispatches blocks on the different threads as needed without having to create, destroy and manage threads yourself)
The processing is not done on the background AFNetworking thread. AFNetworking uses the completionBlock property of NSOperation to do its processing which is executed when finished is set to YES.
The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore, you should not use this block to do any work that requires a very specific execution context. Instead, you should shunt that work to your application’s main thread or to the specific thread that is capable of doing it. For example, if you have a custom thread for coordinating the completion of the operation, you could use the completion block to ping that thread.
the post processing of HTTP connections is handled in AFHTTPRequestOperation. This class creates a dispatch queue specifically for transforming response objects in the background and shunts the work off onto that queue. see here
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
self.completionBlock = ^{
//...
dispatch_async(http_request_operation_processing_queue(), ^{
//...
I guess this begs the question could they have written AFURLConnectionOperation to not make a thread. I think the answer is yes as there is this API
- (void)setDelegateQueue:(NSOperationQueue*) queue NS_AVAILABLE(10_7, 5_0);
Which is meant to schedule your delegate callbacks on a specific operation queue as opposed to using the runloop. But as we're looking at the legacy part of AFNetworking and that API was only available in iOS 5 and OS X 10.7. Looking at the blame view on Github for AFURLRequestOperation we can see that mattt actually wrote the +networkRequestThread method coincidentally on the actual day the iPhone 4s and iOS 5 were announced back in 2011! As such we can reason that the thread exists because at the time it was written we can see that making a thread and scheduling your connections on it was the only way to receive callbacks from NSURLConnection in the background while running in an asynchronous NSOperation subclass.
the thread is created using the dispatch_once function. (see the extra code snipped i added as you suggested) This function ensures that the code enclosed in the block it runs will be run only once in the lifetime of the application. The AFNetworking thread is created when it is needed and then persists for the lifetime of the application
When i wrote NSURLConnectionOperation i meant AFURLConnectionOperation. I corrected that thanks for mentioning it :)
From: Apple docs on managing concurrency:
NsOperation
Write a custom subclass and override one method: main. The main method gets called to perform the operation when the NSOperationQueue schedules it to run. NSOperation classes written in this way are known as non-concurrent operations, because the developer is not responsible for spawning threads—multi-threading is all handled by the super class. (Don’t be confused by the terminology: just because an operation is non-concurrent, does not mean it cannot be executed concurrently, it simply means that you don't have to handle the concurrency yourself.)
I think overriding main is the easiest way to use NSOperation, but the apple site says its non-concurrent does it mean that the nsoperations in the nsoperation queue(when only overriding main) would execute serially?
I don't want to execute my operations serially, but I want to get my operations parallel with as minimum effort as possible.
No, they will not necessarily be run serially. Just as the paragraph you quoted noted, it "does not mean it cannot be executed concurrently".
So what does determine if they can run in parallel? The NSOperationQueue and any dependencies you set up between the ops. A little later in that same document, the section entitled "Running Operations" explains:
you can specify (limit) the number of threads the queue will spawn, and
"NSOperationQueue will automatically determine how many threads it should spawn."
And in the Concurrency Programming Guide it elaborates:
In most cases, operations are executed shortly after being added to a queue, but the operation queue may delay execution of queued operations for any of several reasons. Specifically, execution may be delayed if queued operations are dependent on other operations that have not yet completed. Execution may also be delayed if the operation queue itself is suspended or is already executing its maximum number of concurrent operations.
What you do give up by using non-concurrent operations is that the operation itself isn't intended to set up new threads, etc.
I am not sure about it, but i am using "dispatch_queue_create" to create parallel processes.
Suppose if i want to do two functionalities at same time, i am using the following code. Please see if it will help you,
dispatch_queue_t queue = dispatch_queue_create("FirstOperation", 0ul);
dispatch_async(queue, ^{
//Do your functionality here
dispatch_sync(dispatch_get_main_queue(), ^{
//Do your UI updates here
});
});
dispatch_release(queue);
dispatch_queue_t queue2 = dispatch_queue_create("SecondOperation", 0ul);
dispatch_async(queue2, ^{
//Do your functionality here
dispatch_sync(dispatch_get_main_queue(), ^{
//Do your UI updates here
});
});
dispatch_release(queue2);
I wonder if AppDelegate is thread safe? I currently have an operation running networking tasks on the secondary thread, when the task begins, I would like to set NetworkActivityIndicatorVisible to YES, and when the task is done, set it to NO. Do I have to always call it in the main thread, or I can do it in the current run loop thread?
Thanks
In general, UIKit is not thread safe. While you may be able to "get away" with some things, you should always do UIKit stuff on the main thread. There are a few, well documented, exceptions.
The pattern for doing this from a background thread is simple.
dispatch_async(dispatch_get_main_queue(), ^{
// Put any code you want to execute in the main thread here.
});
The code inside the block you pass to dispatch_async will be scheduled to run in the main run loop.
I'm writing a multi threaded application for iOS.
I am new to Objective-C, so I haven't played around with threads in iPhone before.
Normally when using Java, I create a thread, and send "self" as object to thread. And from the thread I can therefor call the main thread.
How is this done in Objective C?
How can I call the main thread from a thread? I have been trying with NSNotificationCenter, but I get a sigbart error :/
This is how the thread is started:
NSArray *extraParams = [NSArray arrayWithObjects:savedUserName, serverInfo, nil]; // Parameters to pass to thread object
NSThread *myThread = [[NSThread alloc] initWithTarget:statusGetter // New thread with statusGetter
selector:#selector(getStatusFromServer:) // run method in statusGetter
object:extraParams]; // parameters passed as arraylist
[myThread start]; // Thread started
activityContainerView.hidden = NO;
[activityIndicator startAnimating];
Any help would be great!
you accomplish this by adding a message to the main thread's run loop.
Foundation provides some conveniences for this, notably -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] and NSInvocation.
using the former, you can simply write something like:
[self performSelectorOnMainThread:#selector(updateUI) withObject:nil waitUntilDone:NO]
a notification may be dispatched from a secondary thread (often the calling thread).
You can either use performSelectorOnMainThread:withObject:waitUntilDone: or, if you're targeting iOS 4 and later, Grand Central Dispatch, which doesn't require you to implement a method just to synchronize with the main thread:
dispatch_async(dispatch_get_main_queue(), ^ {
// Do stuff on the main thread here...
});
This often makes your code easier to read.
Though this is not a direct answer to your question I would highly recommend you take a look at Grand Central Dispatch. It generally gives better performance than trying to use threads directly.
As Justin pointed out, you can always perform a function in the main thread by calling performSelectorOnMainThread, if you really needed too.