Multiple GCD Dispatches on main thread - iphone

I'm trying to speed up the boot of my app, and one of the ideas i had for that was to use asynchronous dispatch queues. I have 2 tasks that can be run next to each other at startup (quite big tasks actually). However, both of them have a significant part that runs on the main thread (UI code mainly).
dispatch_async(dispatch_get_main_queue, ^{
[self doTask1];
});
dispatch_async(dispatch_get_main_queue, ^{
[self doTask2];
//Will task 2 take turns with task 1, or will task 2 start after 1 is finished?
});
My question is this: If i call 2 dispatch_async's at boot like in this example, will they take turns in executing, or will the complete first block execute first, then the 2nd block?

the main queue is a serial queue. blocks added to serial queues are executed in the order they are added and only one at a time (serially). in your example, task2 will not start until task1 has finished.
if you want them to run concurrently you'll need to dispatch them to one of the global concurrent queues.
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(q, ^{/* this work may finish before other work added to this queue later */});

One will be executed after the other, but they will execute concurrently, meaning you can execute task2 before task1 has finished.
Check the alternative:
dispatch_async(dispatch_get_main_queue, ^{
[self doTask1];
dispatch_async(dispatch_get_main_queue, ^{
[self doTask2];
//Now task2 will execute after task1
});
});

Related

Semaphore is not waiting swift

I'm trying to do 3 async requests and control the load with semaphores to know when all have loaded.
I Init the semaphore in this way:
let sem = dispatch_semaphore_create(2);
Then send to background the waiting for semaphore code:
let backgroundQueue = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
dispatch_async(backgroundQueue) { [unowned self] () -> Void in
println("Waiting for filters load")
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
println("Loaded")
}
Then I signal it 3 times (on each request onSuccess and onFailure):
dispatch_semaphore_signal(sem)
But when the signal code arrives it already passed the semaphore wait code, it never waits to subtract the semaphore count.
why?
You've specified dispatch_semaphore_create with a parameter of 2 (which is like calling dispatch_semaphore_signal twice), and then signal it three more times (for a total of five), but you appear to have only one wait (which won't wait at all because you started your semaphore with a count of 2).
That's obviously not going to work. Even if you fixed that (e.g. use zero for the creation of the semaphore and then issue three waits) this whole approach is inadvisable because you're unnecessarily tying up a thread waiting for the the other requests to finish.
This is a textbook candidate for dispatch groups. So you would generally use the following:
Create a dispatch_group_t:
dispatch_group_t group = dispatch_group_create();
Then do three dispatch_group_enter, once before each request.
In each of the three onSuccess/onFailure blocks pairs, do a dispatch_group_leave in both block.
Create a dispatch_group_notify block that will be performed when all of the requests are done.

Objective-c/iOS: setting status text in async function is slow

In my app I'm doing some communication with a remote server and as this might be slow I thought it would be a good idea to run that code asynchronously. I have my communication code in a block that I pass to dispatch_async. This code does the communication and when it's done it sets the text of a label. This last part is the problem. The text is set, but it occurs after a delay of a few seconds. This is my code.
- (void)doNetworkingTask {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Slow network task goes here.
// Slow network task done, notify the user.
[self.myLabel setText:#"task done."];
NSLog(#"task done.");
});
}
What happens here is that my network task completes, the NSLog-text is logged and after a couple of seconds, the text of the label is updated. My question is 1) why does the label text not update instantly? and 2) what is a proper way of doing what I want to do? (do the slow network task without blocking anything else, update the user through a text label once I'm done.)
UI updates must be on the main thread. Update your code to something like this:
- (void)doNetworkingTask {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Slow network task goes here.
// Slow network task done, notify the user.
dispatch_async(dispatch_get_main_queue(), ^{
[self.myLabel setText:#"task done."];
});
NSLog(#"task done.");
});
}

Grand Central Dispatch problems with dispatch_release

I have a problem with a GCD solution I've made. I have a thread that runs in the background, it updates the application in a given interval. For this I use a timer.
However if the user wants to change this interval, I call
dispatch_source_cancel(timer);
Which is defined as
dispatch_source_set_cancel_handler(timer, ^{
dispatch_release(timer);
});
And then restart the the thread. When the interval is changed a second time the app crashes. Even though I do recreate the timer with a new interval.
I could avoid releasing the timer, but then I'll have memory leeks.
Any advice, what to do?
EDIT:
Timer is created like this
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, autoRefreshQueue);
if(!timer) {
return;
}
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, refreshRate * NSEC_PER_SEC), refreshRate * NSEC_PER_SEC, refreshRate * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
//do work
});
I don't think this is the answer. dispatch_source_cancel doesn't cancel immediately, synchronously.
man dispatch_source_cancel
The dispatch_source_cancel() function asynchronously cancels the dispatch source, preventing any further invocation of its event handler block. Cancellation does not interrupt a currently executing handler block (non-preemptive).
Thus, restarting the thread might invoke the blocks concurrently if autoRefreshQueue is Global Queue.
How did you restart the thread?
EDITED:
However there are no mentions of calling dispatch_source_set_timer twice (or more) for the same Dispatch Source in the references or the manuals, dispatch_source_set_timer in libdispatch/src/source.c seems ok for it. At least, as far as my test, there are no problem.
Thus, just call dispatch_source_set_timer for a new interval.
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, refreshRate * NSEC_PER_SEC), refreshRate * NSEC_PER_SEC, refreshRate * NSEC_PER_SEC);

How to make all threads sleep - iphone

-> I am making an iphone application
-> I have a scenario where I am running number of threads in background.
-> Now suppose on main thread I receive an event and have to execute some action in a new background thread.
->But when I perform some action on the new background thread at that time my all other threads should pause/sleep till the action is completed.
-> Once the action is over all other threads should resume their operation.
I will be exploring more on this, but if any one has idea please provide some input.
Thanks
Usually signalling can be done using pthread conditions,using mutex for synchronizing, Like so:
Create Mutex and Condition Variables:
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
Thread 1: Wait for the Signal:
pthread_cond_wait(&cond, &mutex);
Thread 2 : Signal the thread waiting for condition:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

Premature exit from dispatch_asycn , Grand Central Dispatch

Lets say i am running some code in dispatch async. .. is there a way to terminate the thread it creates before it completes? like when the user clicks cancel
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//start doing something here.. break bofore it finishes?
dispatch_async(dispatch_get_main_queue(), ^{
//main thread stuff..
});
});
David is right. GCD has no built-in method of cancellation. It is up to the client (you).