2012-10-12 175 views
2

我有一個iOS應用程序,從Web服務拉下用戶數據,並將其保存到sqlite支持的核心數據存儲。雖然這也正在進行,我正在爲用戶的頭像提供url,並將圖像保存到核心數據中,因爲每個圖像的下載都可用。解決核心數據死鎖問題?

這些都是在自己的線程上使用自己的託管對象上下文執行的,但使用相同的共享持久性存儲協調器。

當只有幾件物品被拉下時,這個效果很好,但當我們接近100件物品時,我在初始數據加載時頻繁死鎖。當我暫停調試器時,我看到不同的線程通常都在等待executeFetchRequest。

我打開了我的方案中的sql調試,並根據控制檯輸出提取完成,但線程永遠不會繼續。

我還有什麼可以使用或看看爲什麼這些是死鎖或我如何可以防止這些死鎖發生?

+1

的一件事是,如果你遇到這種死鎖的同時調試Xcode中(我確實經常),則可以暫停調試器,看到一個堆棧跟蹤,往往是非常有用的(你會看到哪個線程是掛在什麼功能)。 – borrrden

回答

2

確保你批量更改DB在一起。每次更改後無需調用saveContext。相反,在每十次左右更改之後,保​​存臨時背景環境可能就足夠了。

請參閱一些指針,這篇文章我的:http://www.cocoanetics.com/2012/07/multi-context-coredata/我想與大家分享

+1

與異步儲蓄父/子視圖控制器使用的文章真的幫助。 – adam0101

2

要回答您的確切問題:「我還有什麼可以用來研究爲什麼這些是僵局或我怎樣才能防止這些僵局發生?」,我只能回答一些非常簡單的想法一般是因爲你接近的問題很難:

  • 從你認爲可能發生鎖定的任何地方添加NSLog語句。我發現使用NSLog(@"%s ...YOUR DEBUG STATEMENT", __PRETTY_FUNCTION__)可以幫助您確切地確定哪個函數被調用,以及從哪個隊列執行。

如果我們超越什麼工具都可以(這基本上是沒有什麼用處)的問題,那麼我留下了有關如何調試你描述的系統中的一些建議:

由於一些背景知識:我用2000多個動態下載和顯示的平滑滾動UITableViews動態下載並顯示可變高度的單元格,其中包含完全沒有由於數據處理或繪圖而導致的抖動或延遲的圖像。這個系統最初是使用CoreData設計的,但最終我們轉向直接使用SQLite來解決您遇到的多線程和並行性問題。我不主張切換到SQLite--這是我們在內部做出的決定,以提高速度並減少本地數據庫中的不一致性。我將其作爲我的答案的背景。

我會首先看看你使用Grand Central Dispatch。如果您使用任何dispatch_sync調用,請確保它們不會出現在阻塞運行線程的鏈中。我最初是這樣做的,以確保多個線程不會同時訪問某個託管對象上下文,並且在幾個小時的調試後才發現問題。這些可以偷偷靠近你,因爲dispatch_sync調用可能在其他函數調用的函數中很深。

我確實最終使用了一個事務性系統(非常SQL-y),它具有動態創建的單個查詢/更新隊列,可以確保一次不會發生太多操作。我也有一個完全不同的系統,它會使用一個單獨的串行讀隊列來快速讀取數據庫。如果可能,該隊列的MOC將從其他MOC鏡像。這很沉重,而且比較慢。由於該系統主要在後臺線程上處理,因此與用戶隔離。

CoreData通常很難多線程化。 SQLite稍微簡單一些,不過你必須圍繞它構建大量的特定於應用程序的體系結構才能使其可用。

如果您想發佈有關係統的其他細節,我也許能幫助更具體。希望這有用。