2013-08-29 99 views
6

很多人問類似標題的問題,而是非常不同的目的:dispatch_get_current_queue()已棄用,是否有替代安全的CoreData?

CoreData 要求你跟蹤當前隊列,你當前線程,和您當前的NSOperationQueue的(如果你是一個的NSOperation) ,如果你允許方法調用來自其他類(默認情況下,每個類都允許)。對此沒有「可能」:這是一個很難的要求。

這很好,一般可以很容易地保證:

NSAssert([NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @"You tried to call this method from an external thread, or a queue other than my internal private queue. That's not legal, and will cause data corruption"); 

...除了蘋果已經和過時dispatch_get_current_queue(),顯然是「因爲人們濫用它避開缺少的功能在GCD /他們不瞭解的GCD位「。

注意:通過蘋果的頭文件評論,我對上面的dispatch_get_current_queue()的使用看起來是正確的和非濫用的:整個觀點是我檢查隊列是我創建的私人隊列(Apple聲稱是可以接受的用法)。

撇開一些貶低某些東西的智慧,僅僅是因爲它的實現中存在一些缺陷:(......有人找到了解決方法,被蘋果公司刪除了)具體來說:使用CoreData,你必須跟蹤隊列 - 是否有另一個這樣做的方式是什麼?

(這個問題很重要,因爲:使用CoreData,如果你允許一些意外調用這種方法,你不會得到「崩潰」,你會得到「數據損壞,將顯示在在未來的一些時候,修復它已經太遲了「)

+0

我一直在使用'dispatch_queue_set_specific()'和'dispatch_get_specific()',我在這裏詢問的應用程序:http://stackoverflow.com/questions/12806506/how-can-i-verify-that-我正在運行一個給定的gcd-queue-without-using-dispatch-g,它一直在很好地識別特定的隊列。 Jody對答案的評論提到了在Core Data中使用類似的東西。 –

+0

@BradLarson dispatch_get_specific()非常有趣,謝謝。我不確定當你不在一個區塊內時調用它會發生什麼(正確執行時,你會這樣做,但是我想知道當它出錯時會發生什麼,因爲這是我嘗試的設置以捕捉/斷言/反對) – Adam

+0

我不知道在一個塊的事情。它所測試的所有內容都是分配給此代碼運行的特定隊列的密鑰。正如我在那裏展示的那樣,我使用這個函數來保證特定隊列上的代碼的同步執行,或者通過同步分派一個塊到隊列中,或者通過直接運行代碼(如果已經在該隊列中)。 –

回答

4

performBlock總是在正確的線程中運行它只是使用:

[yourManagedObjectContext performBlock:^{ 
//do your stuff here 
}]; 

您不需要跟蹤當前上下文了,因爲您的MOC知道哪個線程首先觸發此MOC。當您使用performBlockperformBlockAndWait時,您是安全的。

+0

好主意,但它似乎有問題與線程鎖定和性能在複雜的情況下 - 由「問題」我的意思是「也許CoreData的問題,也可能錯誤在我們的代碼庫,可能兩個一起」。我的第一步就是開始大聲說出來,以便找出爲什麼偶爾會出現「CoreData掛在數十秒鐘內看起來無可爭議的互斥體」。 – Adam

+0

...所以我試圖消除我們對'總是執行任何事情塊'的依賴,並找出實際發生的事情/沒有發生 – Adam

+0

「總是執行'所有事情'都是推薦的做法AFAICT。 ''dispatch_get_current_queue()'由於libdispatch的工作方式而在很大程度上沒有用處 - 有少量的「全局」隊列,其他隊列最終會針對在這些隊列上執行的操作。這使得調用無用,因爲哪個是當前隊列?它是否被排入隊列?或者它正在執行的全局隊列中,隊列是你所在隊列的仲裁者,在這種情況下,'performBlock:'是入隊者,並且是瞭解你的唯一方法在那個隊列上。 – ipmcc

0

在我的特定情況下,我換成了所有performBlock電話:

  1. 移動所有的CoreData行動,以一個單一的類
  2. 創建私有dispatch_queue
  3. 合併我所有的內部呼叫到一個單一的呼叫
  4. 單個呼叫在dispatch_async((私有內部隊列)中迴繞)
    1. ...以及它在調度中執行的第一件事h是「if(self.privateMOC == nil)」...並創建本地MOC,低保MOC永遠只能是訪問和creatd上一個隊列

發生了兩件事:

  1. 互斥/鎖掛起已經全部消失了(雖然這可能是巧合 - 如果發現鎖定仍然陷入死鎖,我會在稍後報告)
  2. 性能顯然比performBlock好得多:隨處可用
    1. 注意:我們有很多performBlock調用,並且經常這樣做(敏感數據需要以適中的高頻率更改CoreData MOC內容)。我不知道這是否會是在一個正常的應用程序

一個明顯的區別......所以,現在,我的目的:這已經證明是一個很好的解決方案。我不相信這是對這個問題的「正確的」通用答案,但是......我把它推薦給任何認爲「執行塊」不是看起來像是萬能藥的人。

相關問題