How to stop a thread in iOS7 (created by dispatch_queue_create) - ios

I created this thread in my iOS app, and I'd like to stop it:
dispatch_queue_t myDispatch = dispatch_queue_create("com.myqueue", DISPATCH_QUEUE_CONCURRENT);
myDispatch thread within it invokes dispatch_global_queue and dispatch_main_queue respectively to execute heavy operations and to execute graphics operations.
But in response to a user action in the app can be called another function that uses another queue very similar to myDispatch. If myDispatch thread is terminated, there are no problems, but this call can also occur during the execution of myDispatch thread, and so my app crashes because both thread use the same arrays.
There is a way to stop or kill a thread before its termination? I'd like to kill the thread currently running and start the new thread.

If you want to cancel/stop background work you should be using NSOperation since as far as I know once you dispatch a block with GCD you lose control of it.

To cancel a GCD thread you have to use your own atomic flag.

Related

Clear process flow of NSRunLoop

Digging more than one day....Apple, Google, Slideshare and stackoverflow. But still not clear about NSRunLoop.
Every thread has a runloop by default.Application mainThread has mainRunLoop.
1. If MainRunLoop get input events is it creating new thread to execute it? Then another runLoop created? How then multiple thread and multiple runLoop work? Communicate?
2. If runLoop has no input event/task it sleeps.When a RunLoop ends?
3. Why i should care about runLoop?
4. Where i can use it?
Where i miss that i can't understand the life cycle?
Lets look on your`s list:
Wrong. Threads do not have built-in runloop. They need to be created manually.
Runloop doesn`t create another threads, its immediately executes an event. That is why at the main thread we can see locked interface - by heavy-load tasks in the main thread (UI in iPhone runs on the main thread). Runloops can communicate with each other with the help of mac ports.
Runloop sleeps before the first event come, then wakes up and ends. Only exception - timer, but it will not runloop. Runloop need to start run every time after Event (in the loop). If you call the run, there is already a built-in loop.
Can use to create some threads which must track or execute something periodically. For example, you can create a thread, when runloop for it and then other threads can execute it`s selectors through performSelector. This creates a background query processor, which does not require each time to create a new thread.

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.

What is the difference between dispatch_sync and dispatch_main?

I understand that dispatch_async() runs something on a background thread, and dispatch_main() runs it on the main thread, so where does dispatch_sync() come in?
You don't generally want to use dispatch_main(). It's for things other than regular applications (system daemons and such). It is, in fact, guaranteed to break your program if you call it in a regular app.
dispatch_sync runs a block on a queue and waits for it to finish, dispatch_async runs a block on a queue and doesn't wait for it to finish.
Serial queues run one block at a time, in order. Concurrent queues run multiple blocks at a time, and therefore aren't necessarily in order.
(edit)
Perhaps when you said dispatch_main() you were thinking of dispatch_get_main_queue()?
dispatch_main() is not for running things on the main thread — it runs the GCD block dispatcher. In a normal app, you won't need or want to use it.
dispatch_sync() blocks the current thread until the block completes. This may or may not be the main thread.
If you want to run something on the main thread, you can use dispatch_get_main_queue() to get the main queue and use once of the normal dispatch methods to run a block there.

Why does Apple suggest do dispatch OpenGL commands in a serial background queue when this inevitably leads to crashes?

They suggest:
When using GCD, use a dedicated serial queue to dispatch commands to
OpenGL ES; this can be used to replace the conventional mutex pattern.
I don't understand this recommendation. There is this conflict that I cannot solve:
When the app delegate of an app receives the -applicationWillResignActive call, it must immediately stop calling any OpenGL function.
If the app continues to call an OpenGL function after -applicationWillResignActive returned, the app will crash.
If I follow Apple's recommendation to call OpenGL functions in a serial background queue, I am faced with this seemingly unsolvable problem:
1) After I receive -applicationWillResignActive I must immediately stop calling any further OpenGL functions.
2) But because the serial queue is in the middle of processing a block of code in the background, sometimes the block of code would finish executing after -applicationWillResignActive returns, and the app crashes.
Here is an illustration showing the concurrent "blocks". The main thread receives a full stop message and has to prevent further calls to OpenGL ES. But unfortunately these happen in a background queue which cannot be halted in flight of working on a block:
|_____main thread: "STOP calling OpenGL ES!"_____|
_____|_____drawing queue: "Draw!"_____|_____drawing queue: "Draw!"_____|
Technically I found no way to halt the background queue instantly and avoid further calls to OpenGL in the background. A submitted block of code once running keeps running.
The only solution I found was to NOT call OpenGL ES functions in the background. Instead, call them on the main thread to guarantee that they will never be called after the app lost access to the GPU.
So if it is okay to call OpenGL ES functions in the background, how do you ensure that they never get called after the app resigned active?
Just wait in applicationWillResignActive for the queue to finish all enqueued operations using a dispatch group or a similar mechanism.
You can find an example in the documentation:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, queue, ^{
// Some asynchronous work
});
// Do some other work while the tasks execute.
// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// Release the group when it is no longer needed.
dispatch_release(group);
Beyond Sven's suggestion of using a dispatch group, I've gone a simpler route in the past by using a synchronous dispatch into your rendering serial queue within -applicationWillResignActive:
// Tell whatever is generating rendering operations to pause
dispatch_sync(openGLESSerialQueue, ^{
[EAGLContext setCurrentContext:context];
glFinish();
// Whatever other cleanup is required
});
The synchronous dispatch here will block until all actions in the serial queue have finished, then it will run your code within that block. If you have a timer or some other source that's triggering new rendering blocks, I'd pause that first, in case it puts one last block on the queue.
As an added measure of safety, I employ glFinish() which blocks until all rendering has finished on the GPU (the PowerVR GPUs like deferring rendering as much as they can). For extremely long-running rendered frames I've occasionally seen crashes due to frame rendering still going even after all responsible OpenGL ES calls have finished. This prevents that.
I use this within a few different applications, and it pretty much eliminates crashes due to rendering when transitioning to the background. I know others use something similar with my GPUImage library (which also uses a serial background dispatch queue for its rendering) and it seems to work well for them.
The one thing you have to be cautious of, with this or any other solution that blocks until a background process is done, is that you open yourself up to deadlocks if you're not careful. If you have any synchronous dispatches back to the main queue within blocks on your background queue, you're going to want to remove those or try to make them asynchronous. If they're waiting on the main queue, and the main queue is waiting on the background queue, you'll freeze up quite nicely. Usually, it's pretty straightforward to avoid that.

Difference between dispatch_get_main_queue and dispatch_get_global_queue

I have just started working on iOS and have been going through Apple Reference material on GCD. dispatch_get_global _queue returns a concurrent queue to which one can submit a block to be executed.
However, we can achieve the same using dispatch_get_main_queue as well, right? Then, what exactly is the difference between dispatch_get_global_queue and dispatch_get_main_queue?
The global queue is a background queue and executes its blocks on a non-main thread. The main queue executes its blocks on the main thread.
You should put background work that does not involve changes to the user interface on the global queue, but use the main queue when the blocks make changes to the user interface. A very common pattern, for example, is to execute a "work" block on the global queue, and to have the work block itself dispatch back to the main queue to update a progress indicator.
dispatch_get_main_queue - should be used when you want to manipulate UI elements.
(It gets a background queue that you can dispatch background tasks that are run asynchronously... it won't block your user interface)
dispatch_get_global_queue - Can be used for network calls/core data.

Resources