3

我正在尝试通过 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),如果这有任何意义的话。

有什么想法吗?

非常感谢!

4

1 回答 1

4

你永远不应该dispatch_sync从一个队列上执行的任务到同一个队列。这可以保证在任何串行队列(如主队列)上死锁,并且在并发队列上是个坏主意。有关详细信息,请参阅Apple 的并发编程指南。由于应用程序委托的init方法在主线程上运行,dispatch_sync对主队列造成死锁。

dispatch_async只要您在主线程上运行正常的 NSRunLoop,主队列就可以工作。当然,您的NSLog(@"test . . .")执行可能比您的应用程序委托的 init 方法完成晚得多。

于 2012-06-10T01:25:53.980 回答