2012-06-10 56 views
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(科爾多瓦),如果這是任何意義。

任何想法?

非常感謝!

+0

使用'[NSThread isMainThread]'測試在主線程上第一個 –

+0

我做了。請參閱我的改進示例。 – user1446796

回答

4

你永遠不應該從在隊列上執行的任務到同一隊列dispatch_sync。這可以保證在任何串行隊列(如主隊列)上發生死鎖,並且對併發隊列是不好的想法。有關更多詳細信息,請參閱Apple's Concurrency Programming Guide。由於應用程序委託的init方法在主線程上運行,因此主隊列中的dispatch_sync會導致死鎖。

dispatch_async只要您在主線程上運行正常的NSRunLoop,就會工作。當然你的NSLog(@"test . . .")可能比你的應用程序委託的init方法的完成時間要晚得多。

+0

絕對正確,儘管我不知道dispatch_async爲什麼會失敗。你確定-init被調用? – EricS

+0

從技術上講,你不應該從通過'dispatch_sync'發送到同一隊列的塊'dispatch_sync'。我想'dispatch_async'內的'dispatch_sync'即使是同一個隊列也可以。 – borrrden

+0

謝謝你的提示,我顯然沒有把它煮沸。但是,我相信問題不在於我的代碼在主隊列中執行。請參閱更新後的代碼以獲取解釋。 – user1446796