调度到主队列总是失败

时间:2012-06-10 00:42:37

标签: objective-c ios queue grand-central-dispatch dispatch

我正在尝试通过iOS上的GCD将一些代码发送到主队列,但即使是最简单的测试也总是失败。最后归结为:

static const int TICK_INTERVAL = 1;

#pragma UIApplicationDelegate implementation

- (void) doTick
{
    if (![NSThread isMainThread])
    {
        NSLog(@"Trying to dispatch . . .");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"test . . .");
        });
    }
}

- (void) startUpdate
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        timer_ = [NSTimer
                  scheduledTimerWithTimeInterval:TICK_INTERVAL
                  target:self
                  selector:@selector(backgroundUpdate)
                  userInfo:nil
                  repeats:NO
                  ];

        [[NSRunLoop currentRunLoop]
         addTimer:timer_
         forMode:NSRunLoopCommonModes
         ];

        [[NSRunLoop currentRunLoop] run];
    });

    UIBackgroundTaskIdentifier back =
    [[UIApplication sharedApplication]
     beginBackgroundTaskWithExpirationHandler:^{
         [self doTick];
         [[UIApplication sharedApplication]
          endBackgroundTask:back
          ];
     }];
}

-(void)backgroundUpdate
{
    [self doTick];

    UIBackgroundTaskIdentifier back =
    [[UIApplication sharedApplication]
     beginBackgroundTaskWithExpirationHandler:^{
         [self doTick];
         [[UIApplication sharedApplication]
          endBackgroundTask:back
          ];
     }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            timer_ = [NSTimer
                     scheduledTimerWithTimeInterval:TICK_INTERVAL
                     target:self
                     selector:@selector(backgroundUpdate)
                     userInfo:nil
                     repeats:NO
                     ];

            [[NSRunLoop currentRunLoop]
             addTimer:timer_
             forMode:NSRunLoopCommonModes
             ];

            [[NSRunLoop currentRunLoop] run];
        });
}

- (id) init
{   
    self = [super init];
    [self startUpdate];
    return self;
}

那是我的AppDelegate。 我希望NSLog在主线程中执行以记录上面的测试文本,但没有任何反应。 dispatch_sync代码只是永远等待,我放在块中的断点永远不会到达。

我确保代码不在主线程中执行。在使用dispatch_sync进行测试之前,我在我的应用中尝试了dispatch_async,结果当然基本相同:没有任何反应(没有阻止)。

有趣的是,它似乎不适用于主队列,其他队列(当前队列,全局队列)似乎工作正常。

我在我的应用中使用Phonegap(Cordova),如果这有任何意义。

任何想法?

非常感谢!

1 个答案:

答案 0 :(得分:4)

您永远不应该dispatch_sync从队列中执行的任务到同一个队列。这可以保证在主队列之类的任何串行队列上死锁,并且在并发队列上是个坏主意。有关详细信息,请参阅Apple's Concurrency Programming Guide。由于应用程序委托的init方法在主线程上运行,因此dispatch_sync到主队列会导致死锁。

只要您在主线程上运行正常的NSRunLoop,

dispatch_async到主队列就会起作用。当然,您的NSLog(@"test . . .")可能会在完成申请代表的init方法之后执行。