views:

116

answers:

3

I have a set of tasks that are done repeatedly and instead of creating a new thread each time this user-invoked task needs to be performed, I'd like to use a thread-pool.

In the typical flow to create a new thread, you have to setup an auto-release pool each time the thread entry point is invoked. It seems that the performance for this operation may be trivial according to http://www.mikeash.com/?page=pyblog/autorelease-is-fast.html but what I want to do is avoid the costs associated with setting up and tearing down a lots of these threads during the execution of my app. In other frameworks/languages, I've just retrieved an idle thread and have it do the work. When it's done with the work, the thread gets returned back to the pool.

I don't see any threadpool objects in the iPhone SDK just NSThread. What's a good way to do this?

How I'm setting up my thread:

// create thread using supplied entry point
[NSThread detachNewThreadSelector:@selector(myMethod) 
     toTarget:self 
     withObject:nil];

// thread entry-point
- (void)myMethod {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    *** code that should be run in the new thread goes here ***

    [pool release];
}
+4  A: 

The way you want to go about this is to use an NSOperationQueue, which will hold a queue of tasks to be done and executes as many in parallel as you wish (configurable), each on a background thread. I assume that the implementation re-uses threads after a given operation is complete.

You use NSOperationQueue in conjunction with NSOperations - you can have either synchronous calls in there (since the work is all done on a background thread) or you can still do asynchronous calls with a little more work (have to define a few more methods).

Here's a tutorial you may find of use.

Kendall Helmstetter Gelner
If the application is interrupted (user switches away, view is dismissed, etc) while there are operations in the queue, do they get completed immediately or after the app is reactivated? (presuming that the NSOperationQueue is not released during the lifetime of the app)
Alexi Groove
Whatever has been executed at the time of the switch is all that will be executed. Enqueued items are neither executed in the background or preserved for the next launch.
bbum
However, if you wanted to make sure all operations do execute before the termination of your application, you could use NSOperationQueue's –waitUntilAllOperationsAreFinished method in your applicationWillTerminate: delegate method. Just be sure that you don't take too long in these operations or your application will be force-quit anyways.
Brad Larson
As noted the app will execute what it can before time runs out and the app is killed. I think you would have to call the waitUntilAllOperationsAreFinsihed call as Brad mentioned, because probably if the main thread quits before a background thread the app is considered safe to kill and the app would be terminated before it might otherwise (not to mention the NSOperationQueue is working in the main thread).
Kendall Helmstetter Gelner
A: 

I would recommend using NSOperationQueue for what you want. You can set the number of threads the queue has.

Elfred
A: 

I think the other answers are spot on with NSOperationQueue, but for the sake of completeness you should be aware of these projects:

  • PLBlocks (compiler + runtime support for blocks on iPhone)
  • WiganWallgate (implementation of grand central dispatch on iPhone)
nall