I would suggest using a NSOperationQueue
with a NSInvocationOperation
. The NSOperationQueue
will automatically scale to use as many threads as is optimal under current load, and is intended for executing long running tasks. There is nothing that stops you from calling back to your delegate several times from an operation running on a operation queue.
Setup your queue like this:
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
I assume that you want no extra arguments sent to your task but the delegate to report back to. In this scenario using a plain NSInvocationOperation
is easiest. I also assume that the method that implements the task, and the method that receives the callback are in the same class. Start a task like so:
NSInvocationOperation* operation;
operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(executeTask:)
object:self];
[queue addOperation:operation];
[operation release];
And then implement executeTask:
. Call back to the delegate on the main thread, so that the UI can safely be updated in the callback. You could wait for the callback to complete if you like, but I skip this, all callbacks will be queued on the main thread.
-(void)executeTask:(id)delegate;
{
while (notDone) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[delegate performSelectorOnMainThread:@selector(taskWillProgress:)
withObject:self
waitUntilDone:NO];
// Do stuff
[pool release];
};
}
I have also thrown in a local autorelease pool. This can be necessary when doing lengthy work in background tasks without a run-loop in place. Good practice.