I have an app where I'm downloading a number of resources from the network, and doing some processing on each one. I don't want this work happening on the main thread, but it's pretty lightweight and low-priority, so all of it can really happen on the same shared work thread. That seems like it'd be a good thing to do, because of the work required to set up & tear down all of these work threads (none of which will live very long, etc.).
Surprisingly, though, there doesn't seem to be a simple way to get all of this work happening on a single, shared thread, rather than spawning a new thread for each task. This is complicated by the large number of paths to achieving concurrency that seem to have cropped up over the years. (Explicit NSThreads, NSOperationQueue, GCD, etc.)
Am I over-estimating the overhead involved in spawning all of these threads? Should I just not sweat it, and use the easier thread-per-task approaches? Use GCD, and assume that it's smarter than I about thread (re)use?
Use GCD — it's the current official recommendation and it's less effort than any of the other solutions. If you explicitly need the things you pass in to occur serially (ie, as if on a single thread) then you can achieve that but it's probably smarter just to change, e.g.
[self doCostlyTask];
To:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^()
{
[self doCostlyTask];
dispatch_async(dispatch_get_main_queue(), ^()
{
// most UIKit tasks are permissible only from the main queue or thread,
// so if you want to update an UI as a result of the completed action,
// this is a safe way to proceed
[self costlyTaskIsFinished];
});
});
That essentially tells the OS "do this code with low priority wherever it would be most efficient to do it". The various things you post to any of the global queues may or may not execute on the same thread as each other and as the thread that dispatched them and may or may not occur concurrently. The OS applies the rules it considers optimal.
Exposition:
GCD is Apple's implementation of thread pooling, and they introduced closures (as 'blocks') at the same time to make it usable. So the ^(C-style args){code} syntax is a block/closure. That is, it's code plus the state of any variables (subject to caveats) that the code references. You can store and call blocks yourself with no GCD knowledge or use.
dispatch_async is a GCD function issues a block to the nominated queue. It executes the block on some thread at some time, and applies unspecified internal rules to do so in an optimal fashion. It'll judge that based on factors such as how many cores you have, how busy each is, what it's currently thinking on power saving (which may depend on power source), how the power costs for that specific CPU work out, etc.
So as far as the programmer is developed, blocks make code into something you can pass around as an argument. GCD lets you request that blocks are executed according to the best scheduling the OS can manage. Blocks are very lightweight to create and copy — a lot more so than e.g. NSOperations.
GCD goes beyond the basic asynchronous dispatch in the above example (eg, you can do a parallel for loop and wait for it to finish in a single call) but unless you have specific needs it's probably not all that relevant.
Surprisingly, though, there doesn't seem to be a simple way to get all
of this work happening on a single, shared thread, rather than
spawning a new thread for each task.
This is exactly what GCD is for. GCD maintains a pool of threads that can be used for executing arbitrary blocks of code, and it takes care of managing that pool for best results on whatever hardware is at hand. This avoids the cost of constantly creating and destroying threads and also saves you from having to figure out how many processors are available, etc.
Tommy provides the right answer if you really care that only a single thread should be used, but it sounds like you're really just trying to avoid creating one thread per task.
This is complicated by the large number of paths to achieving
concurrency that seem to have cropped up over the years. (Explicit
NSThreads, NSOperationQueue, GCD, etc.)
NSOperationQueue uses GCD, so you can use that if it makes life easier than using GCD directly.
Use GCD, and assume that it's smarter than I about thread (re)use?
Exactly.
I would use NSOperationQueue or GCD and profile. Can't imagine thread overhead will beat out network delays.
NSOperationQueue would let you limit the number of simultaneous operations, if they end up getting too greedy. In fact, you can limit it to one if you need to.
Related
I'm learning about concurrent programming for iOS. So far I've read about NSOperation/NSOperationQueue and GCD. What are the reasons for using NSOperationQueue over GCD and vice versa?
Sounds like both GCD and NSOperationQueue abstract away the explicit creation of NSThreads from the user. However the relationship between the two approaches isn't clear to me so any feedback to appreciated!
GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD.
In general, you should use the highest level of abstraction that suits your needs. This means that you should usually use NSOperationQueue instead of GCD, unless you need to do something that NSOperationQueue doesn't support.
Note that NSOperationQueue isn't a "dumbed-down" version of GCD; in fact, there are many things that you can do very simply with NSOperationQueue that take a lot of work with pure GCD. (Examples: bandwidth-constrained queues that only run N operations at a time; establishing dependencies between operations. Both very simple with NSOperation, very difficult with GCD.) Apple's done the hard work of leveraging GCD to create a very nice object-friendly API with NSOperation. Take advantage of their work unless you have a reason not to.
Caveat:
On the other hand, if you really just need to send off a block, and don't need any of the additional functionality that NSOperationQueue provides, there's nothing wrong with using GCD. Just be sure it's the right tool for the job.
In line with my answer to a related question, I'm going to disagree with BJ and suggest you first look at GCD over NSOperation / NSOperationQueue, unless the latter provides something you need that GCD doesn't.
Before GCD, I used a lot of NSOperations / NSOperationQueues within my applications for managing concurrency. However, since I started using GCD on a regular basis, I've almost entirely replaced NSOperations and NSOperationQueues with blocks and dispatch queues. This has come from how I've used both technologies in practice, and from the profiling I've performed on them.
First, there is a nontrivial amount of overhead when using NSOperations and NSOperationQueues. These are Cocoa objects, and they need to be allocated and deallocated. In an iOS application that I wrote which renders a 3-D scene at 60 FPS, I was using NSOperations to encapsulate each rendered frame. When I profiled this, the creation and teardown of these NSOperations was accounting for a significant portion of the CPU cycles in the running application, and was slowing things down. I replaced these with simple blocks and a GCD serial queue, and that overhead disappeared, leading to noticeably better rendering performance. This wasn't the only place where I noticed overhead from using NSOperations, and I've seen this on both Mac and iOS.
Second, there's an elegance to block-based dispatch code that is hard to match when using NSOperations. It's so incredibly convenient to wrap a few lines of code in a block and dispatch it to be performed on a serial or concurrent queue, where creating a custom NSOperation or NSInvocationOperation to do this requires a lot more supporting code. I know that you can use an NSBlockOperation, but you might as well be dispatching something to GCD then. Wrapping this code in blocks inline with related processing in your application leads in my opinion to better code organization than having separate methods or custom NSOperations which encapsulate these tasks.
NSOperations and NSOperationQueues still have very good uses. GCD has no real concept of dependencies, where NSOperationQueues can set up pretty complex dependency graphs. I use NSOperationQueues for this in a handful of cases.
Overall, while I usually advocate for using the highest level of abstraction that accomplishes the task, this is one case where I argue for the lower-level API of GCD. Among the iOS and Mac developers I've talked with about this, the vast majority choose to use GCD over NSOperations unless they are targeting OS versions without support for it (those before iOS 4.0 and Snow Leopard).
GCD is a low-level C-based API.
NSOperation and NSOperationQueue are Objective-C classes.
NSOperationQueue is objective C wrapper over GCD.
If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation:
i. implementation
For GCD implementation is very light-weight
NSOperationQueue is complex and heavy-weight
NSOperation advantages over GCD:
i. Control On Operation
you can Pause, Cancel, Resume an NSOperation
ii. Dependencies
you can set up a dependency between two NSOperations
operation will not started until all of its dependencies return true for finished.
iii. State of Operation
can monitor the state of an operation or operation queue.
ready ,executing or finished
iv. Max Number of Operation
you can specify the maximum number of queued operations that can run simultaneously
When to Go for GCD or NSOperation
when you want more control over queue (all above mentioned) use NSOperation
and for simple cases where you want less overhead
(you just want to do some work "into the background" with very little additional work) use GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/
http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html
http://nshipster.com/nsoperation/
Another reason to prefer NSOperation over GCD is the cancelation mechanism of NSOperation. For example, an App like 500px that shows dozens of photos, use NSOperation we can cancel requests of invisible image cells when we scroll table view or collection view, this can greatly improve App performance and reduce memory footprint. GCD can't easily support this.
Also with NSOperation, KVO can be possible.
Here is an article from Eschaton which is worth reading.
GCD is indeed lower-level than NSOperationQueue, its major advantage is that its implementation is very light-weight and focused on lock-free algorithms and performance.
NSOperationQueue does provide facilities that are not available in GCD, but they come at non-trivial cost, the implementation of NSOperationQueue is complex and heavy-weight, involves a lot of locking, and uses GCD internally only in a very minimal fashion.
If you need the facilities provided by NSOperationQueue by all means use it, but if GCD is sufficient for your needs, I would recommend using it directly for better performance, significantly lower CPU and power cost and more flexibility.
Both NSQueueOperations and GCD allow executing heavy computation task in the background on separate threads by freeing the UI Application Main Tread.
Well, based previous post we see NSOperations has addDependency so that you can queue your operation one after another sequentially.
But I also read about GCD serial Queues you can create run your operations in the queue using dispatch_queue_create. This will allow running a set of operations one after another in a sequential manner.
NSQueueOperation Advantages over GCD:
It allows to add dependency and allows you to remove dependency so for one transaction you can run sequential using dependency and for other transaction run concurrently while GCD
doesn't allow to run this way.
It is easy to cancel an operation if it is in the queue it can be stopped if it is running.
You can define the maximum number of concurrent operations.
You can suspend operation which they are in Queue
You can find how many pending operations are there in queue.
GCD is very easy to use - if you want to do something in the background, all you need to do is write the code and dispatch it on a background queue. Doing the same thing with NSOperation is a lot of additional work.
The advantage of NSOperation is that (a) you have a real object that you can send messages to, and (b) that you can cancel an NSOperation. That's not trivial. You need to subclass NSOperation, you have to write your code correctly so that cancellation and correctly finishing a task both work correctly. So for simple things you use GCD, and for more complicated things you create a subclass of NSOperation. (There are subclasses NSInvocationOperation and NSBlockOperation, but everything they do is easier done with GCD, so there is no good reason to use them).
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch.
It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that.
In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like.
So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
I agree with #Sangram and other answers but want to add few points. Correct me if I am wrong.
I think now a days first two points of #Sangram's answer are not valid (i. Control On Operation ii. Dependencies). We can achieve these two by using GCD also. Trying to explain by code(do not focus on quality of code, this is for reference purpose only)
func methodsOfGCD() {
let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
//We can suspend and resume Like this
concurrentQueue.suspend()
concurrentQueue.resume()
//We can cancel using DispatchWorkItem
let workItem = DispatchWorkItem {
print("Do something")
}
concurrentQueue.async(execute: workItem)
workItem.cancel()
//Cam add dependency like this.
//Operation 1
concurrentQueue.async(flags: .barrier) {
print("Operation1")
}
//Operation 2
concurrentQueue.async(flags: .barrier) {
print("Operation2")
}
//Operation 3.
//Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
concurrentQueue.async(flags: .barrier) {
print("Operation3")
}
}
Recently, i am learning concurrency in swift. According to apple's document in NSOperation class reference :
When you add an operation to an operation queue, the queue ignores the value of the asynchronous property and always calls the start method from a separate thread. Therefore, if you always run operations by adding them to an operation queue, there is no reason to make them asynchronous.
does it mean synchronous in a separate thread is the same as asynchronous? and when i do the test with the following code, the operation indeed doesn't block the current main thread.
let operationQueue = NSOperationQueue()
let operation = NSBlockOperation(){
//do some task here
}
operationQueue.addOperation(operation)
so if it is true, then why should we create concurrency subclass of NSOperation?
Oh, NSOperation. Such a bizarre history you have.
NSOperation is relatively old (in iOS terms; fairly modern in ObjC terms). It was added in OS X 10.5. Before OS X 10.6/iOS 4, there were no NSBlockOperation objects. There were no blocks at all. So the only way to make an operation was to subclass or use NSInvocationOperation. Both approaches are cumbersome, but were still easier and more powerful than the older approach of using NSThread directly.
(This was right at the time when multi-core became a thing. 10.5 was famous for adding Core Animation which was I believe the first major preemptive multitasking framework in Cocoa. Before 10.5, most things were done with the runloop and cooperative multitasking, which is actually very efficient and effective for single-core systems. But it doesn't scale well to multi-core systems. Tools like NSOperation were provided to help us write better multi-core code, but GCD was so much more powerful that it completely dominated how multitasking code is written in Cocoa.)
When you subclass NSOperation, you needed to tell the system whether your operation is asynchronous. This isn't a request to run you asynchronously. This is a promise that your start method will not block. It's up to your start method to make sure the operation really is asynchronous.
This is only necessary in the case that your NSOperation is being started manually, and even then it was often not needed. If you put it onto an NSOperationQueue (and you really should always do that), this property is irrelevant. I remember it creating a lot of confusion at the time.
It's become even more irrelevant since the introduction of blocks. It is almost always much easier to use an NSBlockOperation (or dispatch_async) than to subclass NSOperation, which was always a bit tricky to get quite right.
Just in case you haven't already read it, if you want to study Cocoa concurrency, you definitely want to start with the Concurrency Programming Guide.
Asynchronous is always defined relative to the thread that makes a request. So a request is asynchronous relative to thread A if thread A makes a request that runs in thread B such that thread A is able to do other work while thread B is running the request.
If thread B in turn farms out the request to thread C such that thread B is able to do other work while thread C is running the request then that second request is an asynchronous relative to thread B.
It doesn't make sense to just keep farming out the same element of work asynchronously over and over again, of course. But assume the work delegated by thread A to thread B described above can be split up into multiple smaller elements of work. It would be reasonable for thread B to invoke those smaller elements of work asynchronously on threads C, D, etc. This might happen if B provides a service to A such that A doesn't want/need to know the details of how the work gets done; it just wants the work done asynchronously. B knows the details and can decide if/how to accomplish the work via smaller parallel units.
Maybe this question has been asked before in a different form. But I think I am looking at this differently. I am doing some optimisation task for the entire codebase and lots of refactoring and that would server the readability of the code also.
So I found [NSThread sleepForTimeInterval:] method written somewhere and for the delays I always use the GCD's dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{}) method. So the question is which is better?
There's a huge difference.
[NSThread sleepForTimeInterval:]
blocks the current thread. This is terrible if the current thread is the main thread. And it may be fine or terrible on other threads depending on what you are doing.
dispatch_after
doesn't block the current thread. The block is queued up to run at a future time on the designated queue while the current thread continues on its merry way.
Without any specific context, I would say that dispatch_after is the much better approach in almost all cases.
When considering replacing uses of [NSThread sleepForTimeInterval:] with GCD's dispatch_after, there are a couple of things to consider. As #rmaddy said, [NSThread sleepForTimeInterval:] blocks the thread on which it's called. As pointed out, this would be very bad for the main thread, and more generally any thread with a run loop on it (because the run loop will not iterate during that call.)
If you have a thread with a run loop on it, you can "spin" the runloop for some amount of time, which allows other run loop sources to remain responsive while the calling thread of execution remains effectively blocked. Details of spinning a run loop are beyond the scope of the question, but using run loops is yet another way you could solve this problem (although GCD is probably still preferred if you're not pushed into using run loops by some other API that relies on them like, for instance, NSStream.)
The primary high-level reason to avoid blocking threads with [NSThread sleepForTimeInterval:] is that threads are a finite resource. If you were to make a loop spawning many threads, all of which subsequently became blocked by virtue of calling [NSThread sleepForTimeInterval:], you would eventually be unable to create more threads. Thread exhaustion isn't a problem with particularly elegant solutions in the framework, because in general, it's a situation that the framework expects you to avoid, at an architectural level, by using a better abstraction like GCD or run loops.
One other situation where [NSThread sleepForTimeInterval:] will differ substantially from dispatch_after is when there is thread-local storage in play. If your code has done something like [[NSThread currentThread] threadDictionary][#"foo"] = #"bar"; then after [NSThread sleepForTimeInterval:] returns, you will be on the exact same thread, and therefore the value you had put into thread-local storage will still be there. With dispatch_after there is no guarantee that your block will run on the same thread from which it was enqueued. (And the overall likelihood of that happening by chance is fairly low as well in a process with other background tasks in flight.) In general, it's not a great idea to use TLS with GCD. That's generally OK because the ability to capture variables in block closures can solve many of the problems that people have historically used TLS to solve.
Thread-local storage is one of those things that can be extremely useful when it solves a given problem, but can make code brittle in the face of refactorings like this. What's worse is that you might not be able to know that other parts of the code are relying on TLS except by seeing things fail (or act weird).
Long story short, there's not enough info here to say which mechanism is best for your situation. If one were starting from scratch though, I struggle to think of a reason one would choose to block a thread using [NSThread sleepForTimeInterval:] instead of using a more modern deferral mechanism.
For my ios app I am using the main queue and root queue. I have several objects and I want their mehtods to run in the root queue.
So far, what I have been doing is add a dispatch_async for each time I call one of those methods which will ultimately become very troublesome when I will use more queues and want to go back to main queue.
What I am looking for is way to assign objects to the root queue so that their methods are executed in the roof queue. What I mean is I am looking for sth. like this: [[TestClass alloc] initInQueue:testQueue];
It is possible to create this in a manner similar to KVO. You could swizzle all your methods to wrap them into dispatch_* calls, but I would strongly discourage it. The level of magic is too high, and you will almost certainly tie yourself up in knots. Moreover, you can't wrap an arbitrary method in dispatch_async since you can't have a return result from that. But you also can't wrap arbitrary methods in dispatch_sync because you would likely deadlock. The problems of solving the general case will quickly spiral out of control in my opinion.
What you should be asking instead is whether your queue architecture is correct. Do you really need to keep calling so many small methods on other queues? In many cases it is better to encapsulate full work units (i.e. a coherent sequence of operations that take an input and generate a final result) rather than individual method calls. (Once you think in work units, NSOperation suddenly gets a lot more useful.) While it is occasionally useful to wrap an accessor into a queue for thread-safety, this is not a general solution to concurrency.
While there are advantages to getting off of the main queue, this advice shouldn't be over-applied. You can do reasonable amounts of work on the main queue without any problems. We built single-threaded Cocoa apps on computers less powerful than iPhones long before GCD. (The iPhone is probably more powerful than my old PowerBooks and might be more powerful than my original MacBook.) I'm not discouraging queues here, just make sure you're doing it for the right reasons and don't overcomplicate things.
But if you really need to move the work, then I would recommend just being explicit with dispatch_ calls in the method itself. It's a little more typing, but it's much clearer and less error-prone.
I'm learning about concurrent programming for iOS. So far I've read about NSOperation/NSOperationQueue and GCD. What are the reasons for using NSOperationQueue over GCD and vice versa?
Sounds like both GCD and NSOperationQueue abstract away the explicit creation of NSThreads from the user. However the relationship between the two approaches isn't clear to me so any feedback to appreciated!
GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD.
In general, you should use the highest level of abstraction that suits your needs. This means that you should usually use NSOperationQueue instead of GCD, unless you need to do something that NSOperationQueue doesn't support.
Note that NSOperationQueue isn't a "dumbed-down" version of GCD; in fact, there are many things that you can do very simply with NSOperationQueue that take a lot of work with pure GCD. (Examples: bandwidth-constrained queues that only run N operations at a time; establishing dependencies between operations. Both very simple with NSOperation, very difficult with GCD.) Apple's done the hard work of leveraging GCD to create a very nice object-friendly API with NSOperation. Take advantage of their work unless you have a reason not to.
Caveat:
On the other hand, if you really just need to send off a block, and don't need any of the additional functionality that NSOperationQueue provides, there's nothing wrong with using GCD. Just be sure it's the right tool for the job.
In line with my answer to a related question, I'm going to disagree with BJ and suggest you first look at GCD over NSOperation / NSOperationQueue, unless the latter provides something you need that GCD doesn't.
Before GCD, I used a lot of NSOperations / NSOperationQueues within my applications for managing concurrency. However, since I started using GCD on a regular basis, I've almost entirely replaced NSOperations and NSOperationQueues with blocks and dispatch queues. This has come from how I've used both technologies in practice, and from the profiling I've performed on them.
First, there is a nontrivial amount of overhead when using NSOperations and NSOperationQueues. These are Cocoa objects, and they need to be allocated and deallocated. In an iOS application that I wrote which renders a 3-D scene at 60 FPS, I was using NSOperations to encapsulate each rendered frame. When I profiled this, the creation and teardown of these NSOperations was accounting for a significant portion of the CPU cycles in the running application, and was slowing things down. I replaced these with simple blocks and a GCD serial queue, and that overhead disappeared, leading to noticeably better rendering performance. This wasn't the only place where I noticed overhead from using NSOperations, and I've seen this on both Mac and iOS.
Second, there's an elegance to block-based dispatch code that is hard to match when using NSOperations. It's so incredibly convenient to wrap a few lines of code in a block and dispatch it to be performed on a serial or concurrent queue, where creating a custom NSOperation or NSInvocationOperation to do this requires a lot more supporting code. I know that you can use an NSBlockOperation, but you might as well be dispatching something to GCD then. Wrapping this code in blocks inline with related processing in your application leads in my opinion to better code organization than having separate methods or custom NSOperations which encapsulate these tasks.
NSOperations and NSOperationQueues still have very good uses. GCD has no real concept of dependencies, where NSOperationQueues can set up pretty complex dependency graphs. I use NSOperationQueues for this in a handful of cases.
Overall, while I usually advocate for using the highest level of abstraction that accomplishes the task, this is one case where I argue for the lower-level API of GCD. Among the iOS and Mac developers I've talked with about this, the vast majority choose to use GCD over NSOperations unless they are targeting OS versions without support for it (those before iOS 4.0 and Snow Leopard).
GCD is a low-level C-based API.
NSOperation and NSOperationQueue are Objective-C classes.
NSOperationQueue is objective C wrapper over GCD.
If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation:
i. implementation
For GCD implementation is very light-weight
NSOperationQueue is complex and heavy-weight
NSOperation advantages over GCD:
i. Control On Operation
you can Pause, Cancel, Resume an NSOperation
ii. Dependencies
you can set up a dependency between two NSOperations
operation will not started until all of its dependencies return true for finished.
iii. State of Operation
can monitor the state of an operation or operation queue.
ready ,executing or finished
iv. Max Number of Operation
you can specify the maximum number of queued operations that can run simultaneously
When to Go for GCD or NSOperation
when you want more control over queue (all above mentioned) use NSOperation
and for simple cases where you want less overhead
(you just want to do some work "into the background" with very little additional work) use GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/
http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html
http://nshipster.com/nsoperation/
Another reason to prefer NSOperation over GCD is the cancelation mechanism of NSOperation. For example, an App like 500px that shows dozens of photos, use NSOperation we can cancel requests of invisible image cells when we scroll table view or collection view, this can greatly improve App performance and reduce memory footprint. GCD can't easily support this.
Also with NSOperation, KVO can be possible.
Here is an article from Eschaton which is worth reading.
GCD is indeed lower-level than NSOperationQueue, its major advantage is that its implementation is very light-weight and focused on lock-free algorithms and performance.
NSOperationQueue does provide facilities that are not available in GCD, but they come at non-trivial cost, the implementation of NSOperationQueue is complex and heavy-weight, involves a lot of locking, and uses GCD internally only in a very minimal fashion.
If you need the facilities provided by NSOperationQueue by all means use it, but if GCD is sufficient for your needs, I would recommend using it directly for better performance, significantly lower CPU and power cost and more flexibility.
Both NSQueueOperations and GCD allow executing heavy computation task in the background on separate threads by freeing the UI Application Main Tread.
Well, based previous post we see NSOperations has addDependency so that you can queue your operation one after another sequentially.
But I also read about GCD serial Queues you can create run your operations in the queue using dispatch_queue_create. This will allow running a set of operations one after another in a sequential manner.
NSQueueOperation Advantages over GCD:
It allows to add dependency and allows you to remove dependency so for one transaction you can run sequential using dependency and for other transaction run concurrently while GCD
doesn't allow to run this way.
It is easy to cancel an operation if it is in the queue it can be stopped if it is running.
You can define the maximum number of concurrent operations.
You can suspend operation which they are in Queue
You can find how many pending operations are there in queue.
GCD is very easy to use - if you want to do something in the background, all you need to do is write the code and dispatch it on a background queue. Doing the same thing with NSOperation is a lot of additional work.
The advantage of NSOperation is that (a) you have a real object that you can send messages to, and (b) that you can cancel an NSOperation. That's not trivial. You need to subclass NSOperation, you have to write your code correctly so that cancellation and correctly finishing a task both work correctly. So for simple things you use GCD, and for more complicated things you create a subclass of NSOperation. (There are subclasses NSInvocationOperation and NSBlockOperation, but everything they do is easier done with GCD, so there is no good reason to use them).
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch.
It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that.
In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like.
So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
I agree with #Sangram and other answers but want to add few points. Correct me if I am wrong.
I think now a days first two points of #Sangram's answer are not valid (i. Control On Operation ii. Dependencies). We can achieve these two by using GCD also. Trying to explain by code(do not focus on quality of code, this is for reference purpose only)
func methodsOfGCD() {
let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
//We can suspend and resume Like this
concurrentQueue.suspend()
concurrentQueue.resume()
//We can cancel using DispatchWorkItem
let workItem = DispatchWorkItem {
print("Do something")
}
concurrentQueue.async(execute: workItem)
workItem.cancel()
//Cam add dependency like this.
//Operation 1
concurrentQueue.async(flags: .barrier) {
print("Operation1")
}
//Operation 2
concurrentQueue.async(flags: .barrier) {
print("Operation2")
}
//Operation 3.
//Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
concurrentQueue.async(flags: .barrier) {
print("Operation3")
}
}