2012-07-13 76 views
2

我一直在尋找這個問題很長一段時間的解決方案,並且已經達到了一個。保存託管對象上下文在iOS 5的performBlock中創建死鎖

我正在開發具有核心數據的iOS應用程序。我創建了兩個指向同一個持久性存儲協調器的託管對象上下文(MOC)。一個MOC(稱爲self.moc)以主隊列併發啓動,而另一個M0C(稱爲self.bmoc)以私有隊列併發啓動。我確定self.moc只能在主線程上運行,而self.bmoc只能在其performBlockperformBlockAndWait塊中運行。

但是,我遇到了這種奇怪的情況,我的應用程序在[self.bmoc save:nil]行上死機。由於保存操作在performBlock塊內執行,所以我沒有看到它達到死鎖的原因。由於該線凍結,即使使用[self.bmoc save:&error]而不是nil,我也不會收到錯誤。

下面是重現問題的代碼。儘管我有許多類似於下面的功能,但只有這一個產生了問題。我無法確定問題的原因,並非常感謝任何見解。謝謝!

-(void)createEmptyUserData { 
    [self.bmoc performBlock:^{ 
     User* user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:self.bmoc]; 
     /* sets user object */ 
     [self.bmoc save:nil]; 
    }]; 
} 

注意:這段代碼是在主線程中執行的。

+0

任何洞察死鎖發生的地方?任何validateSomething方法或willSave方法鎖定的東西?死鎖意味着2個線程正在彼此等待,另一個線程在哪裏等待? – 2012-07-13 12:19:16

+1

謝謝你的回覆。在這段代碼執行完畢後,主線程繼續運行並結束於'[self。bmoc performBlockAndWait^{}]',它等待上面的代碼完成它的執行,導致主線程凍結。我不知道有任何validateSomething方法或willSave方法。 – 2012-07-13 13:30:04

+0

您可以嘗試添加'-com.apple.CoreData.SQLDebug 3'來打開調試功能並查看是否有任何內容正在保存。 – 2012-07-13 13:44:32

回答

0

在這種情況下,有兩個基本的原因讓你「掛掉」。

  1. 你有一個嵌套調用performBlockAndWait或一些其他同步線程/隊列調用。

  2. 其中一個塊沒有返回,並且永遠運行。

通過在「掛起」時查看每個正在運行的線程的堆棧,可以很容易地看到這兩者。

performBlock只需要執行塊並將其添加到隊列中,然後立即返回。然後一些其他線程將執行塊從隊列中彈出並執行它們。

performBlockAndWait在調用線程的上下文中執行。基本上,它等待當前排隊的執行塊運行,然後它在當前線程上運行所請求的代碼。

直到通話結束,纔會返回。

因此,我敢打賭你要麼執行多個嵌套調用來執行BlockAndWait或者你的一個異步執行塊沒有完成。

查看棧在掛機的時候......

另外,記錄您的塊執行,所以你可以看到每塊啓動和退出時。

+0

這與fabrice truillot de chambrier所說的相似。我會根據您提供的方向深入研究問題,並在稍後再回復。謝謝。 – 2012-07-14 06:02:12

+0

謝謝你引導我回答。稍後我會編輯它,並提供一些有關問題原因以及我如何解決問題的詳細信息。 – 2012-07-15 08:25:33

+1

我以爲我可以編輯評論,但顯然我錯了。無論如何,問題的原因是'[self.bmoc save:nil];'調用'contextDidChange:'保存過程完成後。在我的'contextDidChange:'中,我有'[self.moc performBlockAndWait^{// mergeContext}]'。正如我在我的問題下的評論中所提到的,我的主線程繼續,並以'[self.bmoc performBlockAndWait^{}]'結尾。問題應該變得清楚:兩個隊列正在等待彼此完成,從而導致僵局。我的解決方案是將'contextDidChange:'中的'performBlockAndWait'改爲'lock'和'unlock'。 – 2012-07-15 12:56:26

相關問題