comparison GCD vs. performSelectorInBackground: dispatch_async not in background

13,240

UIKit classes should be used only from an application’s main thread. (From iOS4, drawing to a graphics context is thread-safe.) You can't use UIKit stuff in a background thread.

Thus, you can only use dispatch_async(dispatch_get_main_queue(), block) in this situation.

dispatch_async(dispatch_get_main_queue(), ^(void) {

It will invoke the block on the main thread in the runloop of the main thread.

dispatch_async(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

It will invoke the block in a background thread. You can't use it because you want to use UIKit in the block. And be careful dispatch_async(dispatch_queue_create(, it might cause memory leak, you have to release the serial queue that is created by dispatch_queue_create.

dispatch_sync(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

dispatch_sync waits until the block is done.

dispatch_sync(dispatch_get_main_queue(), ^(void) {

It causes DEADLOCK.

Share:
13,240
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    Grand Central Dispatch is great and reduces the amount of code but why I cannot run something on a background thread?
    I have made a sample application to show what I mean (none of the commented work):

    - (IBAction)performSel {
        [self performSelectorInBackground:@selector(doStuff) withObject:nil];
        [NSThread sleepForTimeInterval:3];
        [[self.view.subviews lastObject] removeFromSuperview];
    }
    
    - (IBAction)gcd {
        dispatch_async(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
        //dispatch_sync(dispatch_queue_create("myGCDqueue", NULL), ^(void) {
        //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        //dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        //dispatch_async(dispatch_get_main_queue(), ^(void) {
        //dispatch_sync(dispatch_get_main_queue(), ^(void) {
            [self doStuff]; // only for readability, will move the code on success
        });
        [NSThread sleepForTimeInterval:3];
        [[self.view.subviews lastObject] removeFromSuperview];
    }
    
    - (void)doStuff {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    
        UIView *abortingView = [[UIView alloc]initWithFrame: self.view.bounds];
        abortingView.backgroundColor = [UIColor whiteColor];
        abortingView.alpha = 0.7;
        [self.view insertSubview:abortingView atIndex:10];
        [abortingView release];
    
        [pool drain];
    }
    

    the [NSThread sleepForTimeInterval:3]; is to simulate a default UI functionality. For example if someone is switching from one navigation view to another.
    Simply copy the code in a new view based application, create two buttons and connect them.

  • shw
    shw almost 12 years
    you shouldn't use dispatch_queue_create("myGCDqueue", NULL) like that because you'd be leaking. you have to release queue you created at some point - usually after dispatching some block onto it