comparison GCD vs. performSelectorInBackground: dispatch_async not in background

独自空忆成欢 提交于 2019-12-03 04:39:04

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/5512641/comparison-gcd-vs-performselectorinbackground-dispatch-async-not-in-background

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!