Matrix
Matrix

Reputation: 7613

looking for a specific example where Operation is preferred over GCD or vice-versa

this question is not about what is the difference between operation queues and dispatch queues. i know that. i have gone through it.

but still in mind, i don't have any such example where i can 100% say that, yeah GCD should be only choice for it. or OperationQueue should be perfect choice for it.

can you give me some example, which explains clear priority of one over another?

because almost everything which can be done by gcd, can be also done by operation queue.

Upvotes: 2

Views: 308

Answers (2)

matt
matt

Reputation: 535617

There isn’t a strong inner difference, because Operations and OperationQueues are GCD under the hood.

However, Operations let you specify triggering mechanisms and dependencies, allowing you to flow / chain asynchronous operations coherently, as described in this brilliant video:

https://developer.apple.com/videos/play/wwdc2015/226/

You couldn’t do that easily with bare GCD.

On the other hand, the new Combine framework might solve the same kind of problem in a nicer way.

Upvotes: 0

Rob
Rob

Reputation: 437917

Nothing’s 100%, but there are cases where you might prefer one over the other:

As a general rule, you might favor GCD because it is more efficient. That having been said, one might favor Operation in these scenarios:

  • You are wrapping a task that, itself, is asynchronous (e.g. a network request), by subclassing Operation.

    For example, Trying to Understand Asynchronous Operation Subclass.

  • You want to encapsulate the logic of some operation in its own object, offering nicer separation of responsibilities.

    For example, let’s say I have a bunch of images that I want to show in my UI, and I want to asynchronously resize them. I don’t want to encumber my view controller (or view, or the view model/presenter) with asynchronous resizing logic. I can wrap that asynchronous resizing logic within its own Operation subclass.

  • You want concurrency, but also want to constrain how many can be done at any given moment in time.

    For example, if processing many images, you might not want to say that you don’t want to do more than 4 at any given time because you want to limit the peak memory usage at any given moment in time. So you’d set the maxConcurrentOperationCount of your OperationQueue.

  • While you can cancel both GCD DispatchWorkItem objects and Operation objects, the implementation within Operation is a little more elegant.

    For example, let’s say I have an Operation that wraps an asynchronous network request. I can write my own cancel override that will cancel the network request. If your tasks consists of some for or while loop, you can achieve cancelation with DispatchWorkItem (e.g. How to stop a DispatchWorkItem in GCD?), but when dealing with a task that is, itself, asynchronous, Operation handles this much better. But even in simple scenarios, I find cancelation within operation queues to be simpler and more intuitive.

  • Operation queues are well suited for those cases where you might have complicated dependencies.

    For example, you have tasks A, B, C, D, and E, but you don’t want C and D to run until after A and B are done, and you only want E to run when C and D are done. Operation queues handle these sorts of scenarios well with “dependencies”.

  • You have a queue with lots of tasks, but they are of differing priorities. With operation queues, each task can have its own queuePriority and the operation queue will tend to favor those higher priority operations over lower priority ones.

Some of those can be achieved within GCD, too, but these are scenarios in which operation queues might be better suited.

That having been said, there are scenarios where GCD is definitely much better suited:

  • I want thread-safe interaction with some object. I want as little overhead as possible when doing that synchronization.

    For example, you might use the reader-writer pattern with a GCD concurrent queue. Then perform reads concurrently with respect to each other with sync, but perform writes asynchronously with a barrier (so they’re never done concurrently with respect to anything else).

  • I just want to quickly dispatch some UI update to the main queue.

    For example, let’s say there is a URLSession task running and in its completion handler (which runs on a background serial queue), I want to update the UI or model object. I would generally just reach for DispatchQueue.main.async { ... }. It is simple and efficient.

  • I want to run a timer on a background queue.

    For example, see How to execute a method every second on a background thread so it doesn't affect the performance of the app?

  • I want to decouple some computational task from UI updates. I might reach for a dispatch merge or add “source”.

    For example, you might be doing some complicated calculation and you want to update a progress indicator, but the updates might come more quickly than the UI can handle them. So we can decouple background tasks from UI updates with dispatch add source. E.g., Long cycle blocks application.

  • I have some computationally intensive task and I want to maximize my use of the cores on my device, but don’t want to exhaust the very limited number of GCD worker threads. In that case, I’d reach for concurrentPerform to parallelize my for loop. (See previous example.)

In short (and to oversimplify), GCD is ideally suited for simple and efficient tasks (or low-level control) and operation queues are well suited for high-level logical units of work.

For more information, also see When are GCD queues used and when do you know you need them?

Upvotes: 3

Related Questions