2014-01-14 90 views
16

我有一個應用程序使用連接隊列來處理後臺線程上的連接。每個連接發送一個JSON帖子,然後當它收到成功時,將一些對象保存到coredata中。主隊列上的dispatch_async塊永遠不會被執行

一旦所有連接完成,我在主線程上調用dispatch_async來調用finished方法。但是,在非常特定的數據發送/保存條件下,我注意到主線程的dispatch_async塊永遠不會被調用,並且應用程序屏幕凍結,所有執行停止,並且應用程序處於閒置狀態屏幕。根據xcode的處理能力爲0%。

這裏是失敗塊的方法。

- (void)connectionDidComplete 
{ 
    _completeConnections++; 

    _syncProgress = (float)_completeConnections/(float)_totalConnections; 

    dispatch_async(mainQueue, ^(void) { 
     [[NSNotificationCenter defaultCenter] postNotificationName:SyncQueueDidUpdateNotification object:nil]; 
    }); <-- this dispatch works 

    if (_completeConnections == _totalConnections) 
    { 
     // clear unsynced data 
     NSArray *syncedObjects = [SyncObject completedSyncObjects]; 

     if (syncedObjects.count > 0) 
     { 
      for (SyncObject *syncObject in syncedObjects) 
      { 
       [syncObject delete]; 
      } 
     } 

     //this method saves the current context, then merges this context with the main context right after 
     [[VS_CoreDataManager sharedManager] saveManagedObjectContextAndWait:managedObjectContext]; 

     // cleanup the thread's context 
     [[VS_CoreDataManager sharedManager] unRegisterManagedObjectContextForThread:currentThread]; 
     managedObjectContext = nil; 

     // complete sync 
     dispatch_async(mainQueue, ^(void) { 
      [self performSelector:@selector(finishSync) withObject:nil afterDelay:2]; 
     }); <-- this dispatch never gets called 
    } 
} 

我懷疑這個問題與保存上下文然後合併它有關。並且可能在合併過程中發佈它,造成一些奇怪的掛斷,並且調度沒有得到執行。這只是一個猜測,但我不知道如何解決它。

任何想法?

謝謝。

+0

不知道爲什麼該塊沒有執行(你有沒有在塊內設置斷點或添加調試日誌消息?),而不是你的'dispatch_async' +'performSelector:withObject:afterDelay:',爲什麼不使用['dispatch_after'](https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/ man3/dispatch_after.3.html)而不是? – DarkDust

+0

+1是否在塊內部獲得。不知道「completedconnections」是否等於「totalconnections」。 – Putz1103

+0

ive在塊中設置斷點,執行沒有達到它 – JMD

回答

21

如果主線程上的塊沒有執行,那是因爲2個原因之一。

  1. 主線程被阻塞;根本不處理任何事件。在主線程上有一段時間()循環?那會做。鎖?你走了。

  2. 主線程在外運行循環內運行模態運行循環。異步調度到主事件循環 - 主線程 - 在這種情況下不會被處理。

設置該dispatch_async()斷點,看到主線程正在做什麼(在分發點的主線程是最有可能已經處於不良狀態)。

DarkDust建議使用dispatch_after()是一個不錯的選擇,但不太可能發揮作用,因爲幾乎可以肯定的是,在發生問題時,主線程不會處理事件。即解決問題,然後按照DarkDust的建議移動到dispatch_after()

+1

設置了斷點之後,我查看了主線程,並且它正在執行一個獲取請求,以查看其隊列計數中剩下多少個連接。這是從OP中第一次派送發出的通知中解僱的。偵聽器調用獲取請求。 – JMD

+0

另一個有趣的事情是,當我點擊dispatch_async行後,所有的線程都被清除了。從字面上看,所有的執行都會消失。 – JMD

+0

@JMD這聽起來像你的主線程是真正楔入,然後。沒有看到更多的代碼,很難說具體在哪裏。最好的猜測是你的通知處理程序正在對進行下載的線程/隊列進行阻塞調用*並且*該線程被阻塞,等待通知被完全處理?即這聽起來像是一個交叉隊列死鎖問題。 – bbum

-1

如果你的主線程忙於模式runloop,那麼你可以嘗試

CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, block 
    }); 
0

我相信這是一個很好的討論。我碰到這個來的時候,我有以下代碼:

dispatch_synch(dispatch_get_main_queue()){ 
     print("I am here") 
    } 

,因爲我是調度造成死鎖串行主線程上的「同步」塊打印的代碼未執行。打印正在等待發送完成併發送等待打印完成。當你在主串行隊列中分派時,你應該使用dispatch_async。我想如果你使用併發隊列然後調度同步適合更好

相關問題