I am using Grand Central Dispatch to run a process in background. I want know how can i suspend, resume and stop that background thread. I have tried
dispatch_suspend(background_thread);
dispatch_resume(background_thread);
but these functions doesn't help me, it keeps on running. Please someone help me.
You seem to have some confusion. Direct manipulation of threads is not part of the GCD API. The GCD object you normally manipulate is a queue, not a thread. You put blocks in a queue, and GCD runs those blocks on any thread it wants.1
Furthermore, the dispatch_suspend man page says this:
The dispatch framework always checks the suspension status before executing a block, but such changes never affect a block during execution (non-preemptive).
In other words, GCD will not suspend a queue while the queue is running a block. It will only suspend a queue while the queue is in between blocks.
I'm not aware of any public API that lets you stop a thread without cooperation from the function running on that thread (for example by setting a flag that is checked periodically on that thread).
If possible, you should break up your long-running computation so that you can work on it incrementally in a succession of blocks. Then you can suspend the queue that runs those blocks.
Footnote 1. Except the main queue. If you put a block on the main queue, GCD will only run that block on the main thread.
You are describing a concurrent processing model, where different processes can be suspended and resumed. This is often achieved using threads, or in some cases coroutines.
GCD uses a different model, one of partially ordered blocks where each block is sequentially executed without pre-emption, suspension or resumption directly supported.
GCD semaphores do exist, and may suit your needs, however creating general cooperating concurrent threads with them is not the goal of GCD. Otherwise look at a thread based solution using NSThread or even Posix threads.
Take a look at Apple's Migrating Away from Threads to see if your model is suited to migration to GCD, but not all models are.
Related
I encountered a problem with non-iOS developer while describing the flow of OperationQueue. We already know that with OperationQueue we can start as many threads as we want to execute the tasks in sync/async way.
But in practical, some of the people want proof for the OperationQueue is getting executed in the background and not with UI(Main) thread.
I just want to demonstrate that when operation queue starts, it already starts its execution in the background.
I already have convinced that when we try to set qos for the operationQueue that we create, it has all the parameters of global queue's qos viz: default userInitiated userInteractive background and utility.
So that is already perfect example in code to prove that all the OperationQueue operations mentioned are run on global thread. Unless we declare the OperationQueue.main
As Shadowrun said, you can add assertions for Thread.isMainThread. Also, if you ever want to add test that you are not on the main queue, you can add a precondition:
dispatchPrecondition(.notOnQueue(.main))
But it should be noted that the whole purpose of creating an operation queue is to get things off the main thread. E.g., the old Concurrency Programming Guide: Operation Queues says [emphasis added]:
Operations are designed to help you improve the level of concurrency in your application. Operations are also a good way to organize and encapsulate your application’s behavior into simple discrete chunks. Instead of running some bit of code on your application’s main thread, you can submit one or more operation objects to a queue and let the corresponding work be performed asynchronously on one or more separate threads.
This is not to say that operation queues cannot contribute to main thread responsiveness problems. You can wait from the main thread for operations added to an operation queue (which is obviously a very bad idea). Or, if you neglect to set a reasonable maxConcurrentOperationCount and have thread explosion, that can introduce all sorts of unexpected behaviors. Or you can entangle the main thread with operation queues through a misuse of semaphores or dispatch groups.
But operations on an operation queue (other than OperationQueue.main) simply do not run on the main thread. Technically, you could get yourself in trouble if you started messing with the target queue of the underlying queue, but I can’t possibly imagine that you are doing that. If you are having main thread problems, your problem undoubtedly rests elsewhere.
Context:
From my understanding, the Main DispatchQueue only dispatch tasks on Main Thread which is for UI mostly.
However the Main Thread can also be used by non-main DispatchQueues.
Apple has QOS to priorities the tasks:
User Interactive: Work that happens on the main thread, such as animations or drawing operations.
User Initiated: Work that the user kicks off and should yield immediate results. This work must be completed for the user to continue.
Utility: Work that may take a bit and doesn’t need to finish right away. Analogous to progress bars and importing data.
Background: This work isn’t visible to the user. Backups, syncs, indexing, etc.
My Question Is:
0, as title described, does thread only contain 2 types, which are Main Thread and Background Thread?
1, does Background Thread mean that all the tasks executed won't block the UI ?
2, Since it mentions that the User Interactive is the priority that the task will be executed on the main thread to avoid UI lags, does it mean all other types: User Initiated, Utility, Background will make sure to have Background Thread that does not block UI?
3, From the link, How to create dispatch queue in Swift 3.
It mentions a couple of different ways to create a Dispatch Queue, some are concurrent, some are serial. It also mentions that by assigning QOS with default or background, it guarantees that the Queue accesses to background threads. But nothing like this mentioned in the Serial and Concurrent. I wonder are those correct?
You ask:
does thread only contain 2 types, which are Main Thread and Background Thread?
I’m not sure if I’d describe them as different “types”, but from the application developer’s perspective, yes, there is the “main” thread, dedicated to the UI, the main run loop, etc., and there are all other threads, which are, in contrast and by definition, “background” threads.
We always want to be careful as to what we run the main queue (i.e. don’t run anything on it that could block that thread and effectively block the UI). In practice, we want to avoid doing anything on the main queue that could block it for more than a few milliseconds, at most.
does Background Thread mean that all the tasks executed won't block the UI?
Effectively, yes. But we’re dealing with limited resources on our devices and therefore the developers must be judicious. For example, for our background tasks, we want to use a QoS that is commensurate for what that queue is doing. Or if parallelizing some task, one should be careful about constraining the degree of concurrency. But if one is judicious about the use of system resources, and keep blocking tasks off the main queue, then that can ensure a responsive UI.
Bottom line, yes, if you have some code that would block the thread on which its run (e.g. it’s computationally expensive, it has blocking calls like semaphores or dispatch group wait, etc.), you would generally run that on a background thread to avoid blocking the main queue.
Since it mentions that the User Interactive is the priority that the task will be executed on the main thread to avoid UI lags, does it mean all other types: User Initiated, Utility, Background will make sure to have Background Thread that does not block UI?
These are just “quality of service” levels, which are just relative priorities for queues. It’s not a question of “block the UI” or “not”, but rather just a matter of how GCD prioritizes and allocates resources.
From the link, How to create dispatch queue in Swift 3. It mentions a couple of different ways to create a Dispatch Queue, some are concurrent, some are serial...
Yes
... It also mentions that by assigning QOS with default or background, it guarantees that the Queue accesses to background threads...
This doesn’t quite make sense. Perhaps you can share the specific excerpt from the docs and we can help you interpret what they were trying to say.
... But nothing like this mentioned in the Serial and Concurrent. I wonder are those correct?
The QoS is just a question of priority and resources for a given queue. Serial vs concurrent is just a question of whether a queue is limited to a single thread at a time, or whether it can avail itself of multiple threads when needed and available.
I'd worked on Java, and pretty much clear with the working of threads and thread pool.
I was wondering if anyone can explain the working of how thread's are created and allocated space in the thread pool in swift ?.
Also, does
Dispatch.main.async {
// some code
}
Creates a new Thread or Asynchronously executes the task ?
Thanks in advance =)
Queues and threads are separate concepts. Queues are ordered (sometimes prioritized) sequences of blocks to execute. As (mostly) an implementation detail, blocks must be scheduled onto threads in order to execute, but this is not the major point of them.
So Dispatch.main.async dispatches (appends) a block to the main queue. The main queue is serial and somewhat special in that it is promised to also be run exclusively on the main thread (as noted by Paulw11). It also promises to be associated with the main runloop. Understanding this "appends a block to a queue" concept is critical, because it has significant impact on how you design things in queues vs how you design things in threads. async does not mean "start running this now." It means "stick this on a queue, but don't wait for it."
As a good example of how the designs can be different, placing something on a queue doesn't mean it will ever run (even without bugs or deadlocks). It is possible and useful to suspend queues so that it stops scheduling blocks. It's possible to tie queues to other queues so that when a queue "schedules" something, it just puts it onto another queue rather than executing it. There are lots of things you can do with queues unrelated to "run things in the background." You can attach completion handlers to blocks. You can use groups to wait on collections of blocks. GCD is a way of thinking about concurrency. Parallelism is just a side benefit. (A great discussion of this concept is Concurrency is not parallelism by Rob Pike. It's in Go, but the concepts still apply.)
If you call Dispatch.main.async while running on the main queue, then that block is absolutely certain to not execute until the current block finishes. In UIKit and AppKit, "the current block finishes" often means "you return from a method that was called by the OS." While not implemented this way, you can pretend that every time you're called from the OS, it was wrapped in a call to Dispatch.main.async.
This is also why you must never call Dispatch.main.sync (note sync) from the main queue. That block will wait for you to return, and you'll wait until the block finishes. A classic deadlock.
As a rule, the thread pool is not your business in iOS. It is an implementation detail. Occasionally you need to think about it for performance reasons, but if you are thinking too much about it, you probably are designing your concurrency incorrectly.
If you're coming from Java, you definitely want to read Migrating Away From Threads in the Concurrency Programming Guide. It's the definitive resource for how to rethink thread-based patterns in queues.
Your code queues the block of code on the main queue (Dispatch.main) and returns immediately (.async), before executing the code.
You do not have control over which thread is used by the queue. Even if you create an own queue:
let serialQueue = DispatchQueue(label: "queuename")
serialQueue.async {
...
}
you do not know which thread your code will be running on.
Update:
As correctly stated by Paulw11 in the comment,
... if you dispatch a task on the main queue, it is guaranteed to execute on the main thread. If you dispatch a task on any other queue, you don't know which thread it will execute on; it may execute on the main thread or some other thread.
I'm an Android engineer trying to port some iOS code that uses 5 SERIAL dispatch queues. I want to make sure I'm thinking about things the right way.
dispatch_sync to a SERIAL queue is basically using the queue as a synchronized queue- only one thread may access it and the block that gets executed can be thought of as a critical region. It happens immediately on the current thread- its the equivalent of
get_semaphore()
queue.pop()
do_block()
release_semaphore()
dispatch_async to a serial queue- performs the block on another thread and lets the current thread return immediately. However since its a serial queue it promises only one of these asynchronous thread is going to execute at a time (the next call to dispatch_async will wait until all other threads are finished). That block can also be thought of as a critical region, but it will occur on another thread. So the same code as above, but its passed to a worker thread first.
Am I off in any of that, or did I figure it out correctly?
This feels like an overly complicated way of thinking of it and there are lots of little details of that description that aren't quite right. Specifically, "it happens immediately on the current thread" is not correct.
First, let's step back: The distinction between dispatch_async and dispatch_sync is merely whether the current thread waits for it or not. But when you dispatch something to a serial queue, you should always imagine that it's running on a separate worker thread of GCD's own choosing. Yes, as an optimization, sometimes dispatch_sync will use the current thread, but you are in no way guaranteed of this fact.
Second, when you discuss dispatch_sync, you say something about it running "immediately". But it's by no means assured to be immediate. If a thread does dispatch_sync to some serial queue, then that thread will block until (a) any block currently running on on that serial queue finish; (b) any other queued blocks for that serial queue run and complete; and (c) obviously, the block that thread A itself dispatched runs and completes.
Now, when you use a serial queue for synchronization for, some thread-safe access to some object in memory, often that synchronization process is very quick, so the waiting thread will generally be blocked for a negligible amount of time as its dispatched block (and any prior dispatched blocks) to finish. But in general, it's misleading to say that it will run immediately. (If it always could run immediately, then you wouldn't need a queue to synchronize access).
Now your question talks about a "critical region", to which I assume you're talking about some bit of code that, in order to ensure thread-safety or for some other reason like that, must be synchronized. So, when running this code to be synchronized, the only question re dispatch_sync vs dispatch_async is whether the current thread must wait. A common pattern, for example, is to say that one may dispatch_async writes to some model (because there's no need to wait for the model to update before proceeding), but dispatch_sync reads from some model (because you obviously don't want to proceed until the read value is returned).
A further optimization of that sync/async pattern is the reader-writer pattern, where concurrent reads are permissible but concurrent writes are not. Thus, you'll use a concurrent queue, dispatch_barrier_async the writes (achieving serial-like behavior for the writes), but dispatch_sync the reads (enjoying concurrent performance with respect to other read operations).
To pick nits, dispatch_sync doesn't necessarily run the code on the current thread, but if it doesn't, it still blocks the current thread until the task completes. The distinction is only potentially important if you're relying on thread IDs or thread-local storage.
But otherwise, yes, unless I missed something subtle.
I was reading OReilly's iOS6 Programming Cookbook and am confused about something. Quoting from page 378, chapter 6 "Concurrency":
For any task that doesn’t involve the UI, you can use global concurrent queues in GCD.
These allow either synchronous or asynchronous execution. But synchronous execution
does not mean your program waits for the code to finish before continuing. It
simply means that the concurrent queue will wait until your task has finished before it
continues to the next block of code on the queue. When you put a block object on a
concurrent queue, your own program always continues right away without waiting for
the queue to execute the code. This is because concurrent queues, as their name implies,
run their code on threads other than the main thread.
I bolded the text that intrigues me. I think it is false because as I've just learned today synchronous execution means precisely that the program waits for the code to finish before continuing.
Is this correct or how does it really work?
How is this paragraph wrong? Let us count the ways:
For any task that doesn’t involve the UI, you can use global
concurrent queues in GCD.
This is overly specific and inaccurate. Certain UI centric tasks, such as loading images, could be done off the main thread. This would be better said as "In most cases, don't interact with UIKit classes except from the main thread," but there are exceptions (for instance, drawing to a UIGraphicsContext is thread-safe as of iOS 4, IIRC, and drawing is a great example of a CPU intensive task that could be offloaded to a background thread.) FWIW, any work unit you can submit to a global concurrent queue you can also submit to a private concurrent queue too.
These allow either synchronous or asynchronous execution. But
synchronous execution does not mean your program waits for the code to
finish before continuing. It simply means that the concurrent queue
will wait until your task has finished before it continues to the next
block of code on the queue.
As iWasRobbed speculated, they appear to have conflated sync/async work submission with serial/concurrent queues. Synchronous execution does, by definition, mean that your program waits for the code to return before continuing. Asynchronous execution, by definition, means that your program does not wait. Similarly, serial queues only execute one submitted work unit at a time, executing each in FIFO order. Concurrent queues, private or global, in the general case (more in a second), schedule submitted blocks for execution, in the order in which they were enqueued, on one or more background threads. The number of background threads used is an opaque implementation detail.
When you put a block object on a concurrent queue, your own program
always continues right away without waiting for the queue to execute
the code.
Nope. Not true. Again, they're mixing up sync/async and serial/concurrent. I suspect what they're trying to say is: When you enqueue a block asynchronously, your own program always continues right away without waiting for the queue to execute the code.
This is because concurrent queues, as their name implies, run their code on threads other than the main thread.
This is also not correct. For instance, if you have a private concurrent queue that you are using to act as a reader/writer lock that protects some mutable state, if you dispatch_sync to that queue from the main thread, your code will, in many cases, execute on the main thread.
Overall, this whole paragraph is really pretty horrible and misleading.
EDIT: I mentioned this in a comment on another answer, but it might be helpful to put it here for clarity. The concept of "Synchronous vs. Asynchronous dispatch" and the concept of "Serial vs. Concurrent queues" are largely orthogonal. You can dispatch work to any queue (serial or concurrent) in either a synchronous or asynchronous way. The sync/async dichotomy is primarily relevant to the "dispatch*er*" (in that it determines whether the dispatcher is blocked until completion of the block or not), whereas the Serial/Concurrent dichotomy is primarily relevant to the dispatch*ee* block (in that it determines whether the dispatchee is potentially executing concurrently with other blocks or not).
I think that bit of text is poorly written, but they are basically explaining the difference between execution on a serial queue with execution on a concurrent queue. A serial queue is run on one thread so it doesn't have a choice but to execute one task at a time, whereas a concurrent queue can use one or more threads.
Serial queue's execute one task after the next in the order in which they were put into the queue. Each task has to wait for the prior task to be executed before it can then be executed (i.e. synchronously).
In a concurrent queue, tasks can be run at the same time that other tasks are also run since they normally use multiple threads (i.e. asynchronously), but again they are still executed in the order they were enqueued and they can effectively be finished in any order. If you use NSOperation, you can also set up dependencies on a concurrent queue to ensure that certain tasks are executed before other tasks are.
More info:
https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
The author is Vandad Nahavandipoor, I don't want to affect this guy's sales income, but all his books contain the same mistakes in the concurrency chapters:
http://www.amazon.com/Vandad-Nahavandipoor/e/B004JNSV7I/ref=sr_tc_2_rm?qid=1381231858&sr=8-2-ent
Which is ironic since he's got a 50-page book exactly on this subject.
http://www.amazon.com/Concurrent-Programming-Mac-iOS-Performance/dp/1449305636/ref=la_B004JNSV7I_1_6?s=books&ie=UTF8&qid=1381232139&sr=1-6
People should STOP reading this guy's books.
When you put a block object on a concurrent queue, your own program
always continues right away without waiting for the queue to execute
the code. This is because concurrent queues, as their name implies,
run their code on threads other than the main thread.
I find it confusing, and the only explanation I can think of, is that she is talking about who blocks who. From man dispatch_sync:
Conceptually, dispatch_sync() is a convenient wrapper around
dispatch_async() with the addition of a semaphore to wait for
completion of the block, and a wrapper around the block to signal its
completion.
So execution returns to your code right away, but the next thing the dispatch_sync does after queueing the block, is wait on a semaphore until the block is executed. Your code blocks because it chooses to.
The other way your code would block is when the queue chooses to run a block using your thread (the one from where you executed dispatch_sync). In this case, your code wouldn't recover control until the block is executed, so the check on the semaphore would always find the block is done.
Erica Sadun for sure knows better than me, so maybe I'm missing some nuance here, but this is my understanding.