Reputation: 251
I have a function on iPad that I need to run 3 steps in sequence, let's say task1, task2, task3. Task2 needs load some data from server. So I need to put task2 into a separate background thread.
- (IBAction)dbSizeButton:(id)sender {
//Task1......
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
//Task2 .....which go to server and download some stuff and update database.
dispatch_sync(dispatch_get_main_queue(), ^{
//Task3, continue to work on UI
});
});
}
But looks like what is happening is the app often got killed when Task2 starts. I am not sure exactly why. I can see Task2 does execute in a separate thread. So I am wondering, if that is not the way to do it, instead of using GCD, can I at the end of Task2 send a message or a notification to the main thread so I can kick off Task3? How exactly to do that?
Upvotes: 1
Views: 3329
Reputation: 535304
The problem is merely your use of dispatch_sync
, which blocks. That's why you're being killed. You almost had it right. What you want is:
// ... task 1 on main thread
dispatch_async(other_queue, ^{
// ... task 2 in background thread
dispatch_async(dispatch_get_main_queue(), ^{
// ... task 3 on main thread
});
});
That is the standard pattern for getting off the main thread and coming back on. That's all there is to it!
Upvotes: 5
Reputation: 12254
What you want to achieve will be done easier by using NSOperation's and NSOperationQueue's instead of the GCD. It doesn't fire notifications, but I believe it does what you want to do.
If I am understanding your problem correctly, you are currently running task1 in the main thread. Task2 is later fired concurrently via task1, but task2 tells task3 to call the UI. So in other words, task2 and task3 depend on task1, right?
Using NSOperations (An operation is a piece of code, either a selector or a block, that you can run in a different thread) and NSOperationQueues, you can achieve those dependencies in less than a minute.
//Assuming task1 is currently running.
NSOperationQueue *downloadAndUpdate; //Leaving out initialization details.
NSOperationBlock *task2; //Leavign out initialization details.
NSOperationBlock *task3;
//This is where it gets interesting. This will make sure task3 ONLY gets fired if task2 is finished executing.
[task3 addDependency:task2];
//Task3 could have the following code to update the main thread.
[[NSOperationQueue mainQueue] addOperation:myUIUpdatingTask];
These APIs are at a higher level than the GCD, and I definitely recommend you learn how to use them to create better concurrency.
Here's a tutorial To help you get started with these APIs.
(DISCLOSURE: I'm the author of this post, but I promise my intention is not to advertise my work. I wrote this tutorial because I needed a better way to do concurrency than the GCD and ended up learning this. I like to teach what I learn).
Upvotes: 2