Online Book Reader

Home Category

Learn Objective-C on the Mac - Mark Dalrymple [159]

By Root 988 0
dispatching function, passing work back to the main thread! We do this by once again calling dispatch_async(), this time passing in the queue returned by the dispatch_get_main_queue() function, which always gives us the special queue that lives on the main thread, ready to execute blocks that require the use of the main thread.

Concurrent Blocks


We still have one more change to make, in order to make this behave the same and run at least as fast as our previous version that used NSOperationQueue. Remember that when we set up operations in the queue, we allowed calculateFirstResult and calculateSecondResult to run at the same time, through the use of dependencies? We declared that each of them was dependent on the preceding call to processData, and that in turn the following call to finishWorking was dependent on both of them. That left it up to the operation queue to run both of those at the same time if possible. In what we currently have in our GCD version, that’s not the case. The code runs straight through just as shown, always calling calculateSecondResult: only after calculateFirstResult: has completed.

Fortunately, once again GCD has a way to accomplish the same thing, by using what’s called a dispatch group. All blocks that are dispatched asynchronously within the context of a group are set loose to execute as fast as they can, including being distributed to multiple threads for concurrent execution if possible. We can also use dispatch_group_notify() to specify an additional block that will be executed when all the blocks in the group have been run. Here’s what it looks like:

One complication here is that each of the calculate methods returns a value which we want to grab, so we have to first create the variables using the __block prefix, which means that the values set inside the blocks are made available to the code that runs later.

With all that in place, you should be able to Build & Run your app, and see the same behavior and performance that you saw after the first set of improvements (but not the additional changes we made, where we used Cocoa Bindings to improve the GUI’s behavior while the work is being performed; applying the changes to the block-enhanced version of SlowWorker is left as an exercise for the reader). The difference lies in the structuring of the code itself. Remember that in Snow Leopard, NSOperationQueue has been reimplemented using GCD, so your app will have similar performance characteristics either way. It’s up to you to decide which way you want to go.

Another Option: NSBlockOperation


Apart from what we’ve already shown, there’s another option for implementing concurrency on Snow Leopard, using a hybrid of the two approaches we’ve seen so far. Snow Leopard includes a new NSOperation subclass called NSBlockOperation that you create an operation using a block instead of an NSInvocation, like this:

Such an operation should be added to an NSOperationQueue in the usual way, where it can be freely mixed with NSInvocationOperation instances. NSBlockOperations are not meant to be used with low-level GCD functions like dispatch_group_async(). The idea is that if you choose to stick with NSOperationQueue instead of GCD queues, you still get the other benefits of using blocks by using NSBlockOperation.

A Little Concurrency Goes a Long Way


You’ve now seen some concrete examples of how to provide basic concurrency in your applications using both NSOperationQueue and GCD. Our simple example project doesn’t do anything interesting, but these techniques can be applied to any situation where you have lengthy activities going on, and don’t want to expose your users to the spinning busy-cursor. You’ve also learned a bit about the new block syntax and how it can be used with GCD’s dispatching functions to do work on background threads. Snow Leopard provides even more ways to use blocks, adding dozens of new methods to existing Cocoa classes. You’ll learn about some of those, and a whole lot more, in our final chapter: Future Paths.

Chapter17

Future Paths

Return Main Page Previous Page Next Page

®Online Book Reader