Is there a way to manually process a DispatchQueue in iOS - ios

I'm working on a game that I'm wanting to add cloud saves via GameKit. The original save code was based on synchronous file I/O and blocks the main queue. Moving away from this design would be a massive amount of work. Unfortunately, it seems like the GameKit APIs dispatch callbacks on the main queue which causes a deadlock in this case.
Given this, is there a way to manually process the blocks in a dispatch queue? That way the blocking code could process the main queue while waiting for the callbacks, eliminating the deadlock.

You can setup a chain of responsibility using Operations. Setup the dependencies between each operation, and then drop them in their respective queues using Grand Central Dispatch.
UI code should be in main and there’s Quality Of Services for background tasks and USER generated activity. You can create a dispatch queues and set them to be synchronous (serial) or asynchronous (parallel).
If you include code, I will post examples. Otherwise there’s several options on how to do the above.

Related

How to make sure that OperationQueue tasks are always getting executed on background(global) thread in swift?

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.

GCD: does thread only has two types? main thread and background thread

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.

What is the difference between 'thread' and 'queue' in iOS development? [duplicate]

This question already has answers here:
Use of the terms "queues", "multicore", and "threads" in Grand Central Dispatch
(3 answers)
Closed 8 years ago.
I am new to iOS development. Now I am quite confused about the two concepts: "thread" and "queue". All I know is that they both are about multithread programming. Can anyone interpret those two concepts and the difference between them for me?
Thanks in advance!
How NSOperationQueue and NSThread Works:
NSThread:
iOS developers have to write code for the work/process he want to perform along with for the creation and management of the threads themselves.
iOS developers have to be careful about a plan of action for using threads.
iOS developer have to manage posiable problems like reuseability of thread, lockings etc. by them self.
Thread will consume more memory too.
NSOperationQueue:
The NSOperation class is an abstract class which encapsulates the code and data associated with a single task.
Developer needs to use subclass or one of the system-defined subclasses of NSOperation to perform the task.
Add operations into NSOperationQueue to execute them.
The NSOperationQueue creates a new thread for each operation and runs them in the order they are added.
Operation queues handle all of the thread management, ensuring that operations are executed as quickly and efficiently as possible.
An operation queue executes operations either directly by running them on secondary threads or indirectly using GCD (Grand Central Dispatch).
It takes care of all of the memory management and greatly simplifies the process.
If you don’t want to use an operation queue, you can also execute an operation by calling its start method. It may make your code too complex.
How To Use NSThread And NSOperationQueue:
NSThread:
Though Operation queues is the preferred way to perform tasks concurrently, depending on application there may still be times when you need to create custom threads.
Threads are still a good way to implement code that must run in real time.
Use threads for specific tasks that cannot be implemented in any other way.
If you need more predictable behavior from code running in the background, threads may still offer a better alternative.
NSOperationQueue:
Use NSOperationQueue when you have more complex operations you want to run concurrently.
NSOperation allows for subclassing, dependencies, priorities, cancellation and a supports a number of other higher-level features.
NSOperation actually uses GCD under the hood so it is as multi-core, multi-thread capable as GCD.
Now you should aware about advantages and disadvantages of NSTread and NSOperation. You can use either of them as per needs of your application.
Before you read my answer you might want to consider reading this - Migrating away from Threads
I am keeping the discussion theoretical as your question does not have any code samples. Both these constructs are required for increasing app responsiveness & usability.
A message queue is a data structure for holding messages from the time they're sent until the time the receiver retrieves and acts on them. Generally queues are used as a way to 'connect' producers (of data) & consumers (of data).
A thread pool is a pool of threads that do some sort of processing. A thread pool will normally have some sort of thread-safe queue (refer message queue) attached to allow you to queue up jobs to be done. Here the queue would usually be termed 'task-queue'.
So in a way thread pool could exist at your producer end (generating data) or consumer end (processing the data). And the way to 'pass' that data would be through queues. Why the need for this "middleman" -
It decouples the systems. Producers do not know about consumers & vice versa.
The Consumers are not bombarded with data if there is a spike in Producer data. The queue length would increase but the consumers are safe.
Example:
In iOS the main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widget and this includes the drawing events, basically the UI that the user sees & interacts.
If you touch a button on screen, the UI thread dispatches the touch event to the app, which in turn sets its pressed state and posts an request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.

Suspending and resuming Grand Central Dispatch thread

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.

With NSOperationQueue, how do you add to a background queue instead of main, and how does controlling amount of operations work?

I'm loving NSOperationQueue but I'm having some issues understanding some portions of it.
In the second issue of objc.io they go over NSOperationQueue and mention that it has two kinds of queues, the main queue which runs on the main thread, and the background queues. They mention you can access the main queue with [NSOperation mainQueue] and then add manipulate it.
You normally would not want to do this, correct? If it's running on the main thread, will it not block the main thread for other tasks? Wouldn't it not run concurrently with other tasks?
It also mentions you can add to the background queues (which I understand would be better?) by creating instances of NSOperation (subclasses potentially).
Do I save a reference to the NSOperationQueue that I create for operations in order to have for creating more operations? I assume there's no singleton for background queues like there is for mainQueue, so how do I manage adding tasks to background queues?
It also mentions you can control the amount of operations running concurrently with the maxConcurrentOperationCount property.
I know normally you set it to NSOperationQueueDefaultMaxConcurrentOperationCount, but if I set it to a specific number manually, does it correspond to the maximum number of threads that can be run at once? For example if the processor on the iPhone can run 4 threads at once and I set that property to 8, what happens?
You ask:
You normally would not want [to add operations to the mainQueue], correct? If it's running on the main thread, will it not block the main thread for other tasks? Wouldn't it not run concurrently with other tasks?
Yes, you would never want to add anything slow to the main queue. But that doesn't mean that you don't use the main queue. For some operations (e.g. UI updates) it's critical.
The typical pattern is to create a operation queue for tasks that you want to run in the background, but if you subsequently need to do something that needs to run on the main queue (e.g. UI updates, updating the model, etc.), you would go ahead and do that, for example:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// do some time consuming stuff in the background
// when done, you might update the UI in the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// update the UI here
}];
];
You ask:
Do I save a reference to the NSOperationQueue that I create for operations in order to have for creating more operations? I assume there's no singleton for background queues like there is for mainQueue, so how do I manage adding tasks to background queues?
Yes, if you want to add more operations to that same queue later, yes, you want to maintain a reference to that queue. You can do this by adding it to the app delegate, some central view controller, or a singleton.
But yes, there's no built-in singleton for background queues (because you can, conceivably have different queues for different operations, e.g. one for network operations, one for image processing, etc.). But you can write your own singleton for each queue of each type, if you want.
You also ask:
I know normally you set it to NSOperationQueueDefaultMaxConcurrentOperationCount, but if I set it to a specific number manually, does it correspond to the maximum number of threads that can be run at once? For example if the processor on the iPhone can run 4 threads at once and I set that property to 8, what happens?
One should set maxConcurrentOperationCount to be whatever you think is appropriate for the type of queue. For network operation queue, you generally wouldn't exceed 4, but for other types of queues, you might easily have more. I believe that there is a maximum of 64 worker threads (which concurrent queues avail themselves as they need threads).
If you attempt to use more than that, the app won't start your operation until a worker thread becomes available. Apple advises, though, that one refrain from using up all of the worker threads. So use a reasonable number appropriate for your queue's function. Frankly, one of the advantages of operation queues over dispatch queues is that you can constrain the maximum number of worker threads that will be used at any given time to better manage the device's limited resources.
References
WWDC 2012 video Asynchronous Design Patterns with Blocks, GCD, and XPC is an excellent primer on some GCD patterns and touches upon the "too many threads" question.
The Building Concurrent User Interfaces on iOS video walks through some practical implications of building concurrent iOS apps.
The About Threaded Programming section of the Threading Programming Guide touches upon the relationship between cores and threads.
The Concurrency and Application Design section of the Concurrency Programming Guide is an articulate discussion of the relationships between threads and operation/dispatch queues.
Generally you don't want to use the main queue. Any operation there will run on the main thread.
When you create an operation queue, create it for a purpose. Like it will be used for all server requests. So you can control how many concurrent requests are in progress. So don't add algorithmic processing operations to this queue because they have a different purpose. Keep a reference to the queue so you can add operations in future (and pause / cancel operations).
There is no 'normal' setting for maxConcurrentOperationCount - it should be set based on the purpose.
If you set it to 8 then the queue will run up to 8 at the same time. This may not be the most efficient option. Always keep the purpose of the queue in mind.
First of all, you will have to keep in mind that you always separate the main thread with the background thread. Only the operations which involve updating the UI must be performed in the main thread and rest of the operations must be performed in the Background thread. e.g if you are dealing with the multiple downloads, then you have to take care of all the network based operations in the background queue, and you will have to perform the UI update in the main queue.
//e.g for updating UI in main thread.
[self performSelectorOnMainThread:#selector(updateUI) withObject:nil waitUntilDone:YES];
Also when you use set maxConcurrentOperationCount property as NSOperationQueueDefaultMaxConcurrentOperationCount, it means the operationQueue takes the number of concurrent operations depending on the system environment.
Useful Links:
http://mobile.tutsplus.com/tutorials/iphone/nsoperationqueue/
http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/

Resources