简体   繁体   中英

Objective-C : Start an object on a background thread — interact as usual?

I would like to have an object be callable from the main thread

MyObj* backgroundObject = [[MyObj alloc] initInBackground];
BOOL result = [backgroundObject computeResult];

But have all the methods of backgroundObject compute in another thread.

And also have backgroundObj be able to send messages to it's delegate. How can I do such a thing? Is it possible?

As others have pointed out, an NSObject doesn't exist on any one thread, a thread only comes into play when you start executing its methods.

My suggestion would be to not use manual threads for every time that a method is called on the object, but instead use NSOperations and an NSOperationQueue. Have an NSOperationQueue as an instance variable of the object, and have calls to the various methods on the object create NSOperations which are inserted into the queue. The NSOperationQueue will process these operations on a background thread, avoiding all of the manual thread management you would need to have for multiple accesses to methods.

If you make this NSOperationQueue have a maximum concurrency count of 1, you can also avoid locking shared resources within the object between the various operations that will be performed on a background thread (of course you'll still need to lock instance variables that can be accessed from the outside world).

For callbacks to delegates or other objects, I'd recommend using -performSelectorOnMainThread:withObject:waitUntilDone so that you don't have to think about making those delegate methods threadsafe.

See the Concurrency Programming Guide for more.

Sure, you can use NSThread for that, and have backgroundObject use performSelectorOnMainThread: to contact the delegate.

Objects do not exist in threads AFAIK. The function you send to an object will always be performed on the thread you sent it from (unless you use NSThread or performSelectorOnMainThread or something along those lines).

What you need is a NSOperation and a block/delegate parameter to notify the caller of completion.

Look at the documentation of NSOperation and NSOperationQueues

You should use GCD :

/*
 * I didn't initalised your object in background, because
 * because in the most cases you need your object to stick around
 * and only perfom the time consimung calculations in background
 */

MyObj* backgroundObject = [[MyObj alloc] initInBackground];
...

- (void)startBackgroundTask {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //in a perfectly async non blocking block :-)
        BOOL result = [backgroundObject computeResult];

        dispatch_async(dispatch_get_main_queue(), ^{
        //post your result, or do something else with your result
            [[NSNotificationCenter defaultCenter] postNotificationName:"backgroundComputeResultDone" object:[NSNumber numberWithBool:result]];

            if (result) {
                //do some stuff
            }
        });
    });
}

Maybe you can take a look at these two videos from apple here :

  • WWDC 2011 - Session 210 - Mastering Grand Central Dispatch
  • WWDC 2011 - Session 308 - Blocks and Grand Central Dispatch in Practice

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM