我正在通過新創建的NSManagedObjectContext在後臺線程(使用GCD)上執行一個代價高昂的獲取(約5秒,約30,000個對象)由後臺線程擁有。主線程在後臺線程執行時等待[NSManagedObjectContext(_NSInternalAdditions)lockObjectStore]
但是,我沒有得到在後臺執行此操作的好處,因爲主線程正在等待持久存儲上的鎖定並因此UI被凍結。這裏的堆棧跟蹤:
* thread #1: tid = 0x1c03, 0x3641be78 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore], stop reason = breakpoint 1.1
frame #0: 0x3641be78 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore]
frame #1: 0x36432f06 CoreData`-[_PFManagedObjectReferenceQueue _processReferenceQueue:] + 1754
frame #2: 0x36435fd6 CoreData`_performRunLoopAction + 202
frame #3: 0x35ab9b1a CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 18
frame #4: 0x35ab7d56 CoreFoundation`__CFRunLoopDoObservers + 258
frame #5: 0x35ab80b0 CoreFoundation`__CFRunLoopRun + 760
frame #6: 0x35a3b4a4 CoreFoundation`CFRunLoopRunSpecific + 300
frame #7: 0x35a3b36c CoreFoundation`CFRunLoopRunInMode + 104
frame #8: 0x376d7438 GraphicsServices`GSEventRunModal + 136
frame #9: 0x33547cd4 UIKit`UIApplicationMain + 1080
frame #10: 0x000f337a MyApp`main + 90 at main.m:16
我(相信)我已經證實了我不是訪問主線程的NSManagedObjectContext而這個後臺線程正在做的工作。從堆棧跟蹤中,很明顯,我沒有直接對Core Data做任何事情。但是有一些事件觸發了對_processReferenceQueue的調用:這導致試圖鎖定商店。有沒有人碰巧知道這個方法做了什麼,以及如何防止它在我的後臺線程執行其工作時被調用?
編輯
我開球此背景下取後,我沒有做任何核心數據讀取或在主線程上寫道。這就是爲什麼這是如此令人費解。如果主線也在嘗試做更多的工作,我預計會有爭議,但這不是 - 至少,我沒有要求它。沒有讀,不寫,沒有FRC。這就是爲什麼我想知道是否有人熟悉這個_processReferenceQueue方法。爲什麼會被叫?我能做些什麼,導致它運行?
編輯
作爲測試,我試圖讓MT的MOC進入狀態,它沒有未決的改變之前,我設置了藍牙功能關閉做的獲取,在希望它不會需要在_processReferenceQueue
中做任何需要商店鎖定的工作。
在開始BT之前,我注意到在[MOC updatedObjects]
集合中有一個對象。插入或刪除的組中沒有對象。
在調用[MOC save]
之後,[MOC updatedObjects]
集合就像預期的那樣是空的。
但是,一旦我開始BT,MT仍然試圖鎖定店內_processReferenceQueue
,儘管沒有什麼在MOC中應該是髒的。
我試過的下一件事(嚴格來說就是測試)是在開始BT之前調用[MOC reset]
。如預期的那樣,[MOC updatedObjects]
集合在重置之後也是空的。在代碼中的這一點上,我沒有觸及MT上的任何託管對象,直到BT完成其工作(所以我沒有遇到任何問題,因爲重置使我已經引用的託管對象無效)。然而,這一次,MT確實不是試圖鎖定_processReferenceQueue
中的持久存儲。
這種行爲暗示了我在啓動BT後沒有對MT上的MOC進行任何明確的操作。否則,MT會在_processReferenceQueue
內部或外部的某個點(讀取或寫入)請求鎖定。但事實並非如此。
我不確定爲什麼最近保存的MOC需要後續鎖定_processReferenceQueue
而最近重置的MOC不需要。
我會繼續挖掘。
謝謝! 布賴恩
我有一個想法,但今天通過回答一個缺乏信息的問題已經燒了兩次。請在後臺線程中發佈更多關於你在做什麼的信息,以及你在主線程中做什麼(例如,你是否在後臺執行任何寫操作,主線程中是否有FRC)。 ..等 –
另外,請記住,您不能跨線程傳遞提取的對象。在後臺使用這些30k對象,或傳遞其ID。 –
以上更新。此外,即使我僅僅在背景上執行提取並忽略結果(作爲測試),MT上的鎖定也會發生。我確實將objectID傳回MT。 – BrianJStafford