比较GCD与performSelectorInBackground:dispatch_async不在后台

时间:2011-04-01 11:19:22

标签: multithreading asynchronous background grand-central-dispatch performselector

Grand Central Dispatch很棒并且减少了代码量,但为什么我不能在后台线程上运行某些东西呢? 我做了一个示例应用程序来显示我的意思(没有评论的工作):

- (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];
}

[NSThread sleepForTimeInterval:3];是模拟默认的UI功能。例如,如果有人正在从一个导航视图切换到另一个导航视图 只需在基于新视图的应用程序中复制代码,创建两个按钮并连接它们。

1 个答案:

答案 0 :(得分:24)

UIKit类只能从应用程序的主线程中使用。 (从iOS4开始,绘图到图形上下文是线程安全的。)你不能在后台线程中使用UIKit东西。

因此,在这种情况下,您只能使用dispatch_async(dispatch_get_main_queue(),block)。

dispatch_async(dispatch_get_main_queue(), ^(void) {

它将在主线程的runloop中调用主线程上的块。

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

它将在后台线程中调用该块。你不能使用它,因为你想在块中使用UIKit。并且要小心 dispatch_async(dispatch_queue_create(,它可能导致内存泄漏,您必须释放由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一直等到块完成。

dispatch_sync(dispatch_get_main_queue(), ^(void) {

导致DEADLOCK。