2015-10-05 60 views
0

我有一個類似的方法:「performBlockAndWait:」塊不執行

- (void)handleUpdate 
{ 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"]; 

     [self.privateContext performBlockAndWait: ^{ 
     // Some processing 
     }]; 
    }); 
} 

我叫mainContext關聯到主隊列,並privateContext關聯到一個專用隊列,是mainContext的孩子。這種方法是從privateContext的私有隊列調用,而且它不是nil達到performBlockAndWait:呼叫時,但執行不進入塊既不達到此方法後的任何代碼...

我該怎麼辦在這裏失蹤?

在此先感謝

編輯:我得到在Xcode中沒有錯誤,我已經在performBlockAndWait:塊內,調用此方法後代碼中設置斷點只是沒有達到。

編輯2:我校正代碼段,我沒有訪問mainContext但關聯到mainContext對象的數組。

+0

任何特定的原因,當你已經在私人環境中的第一個地方時,你爲什麼得到主要上下文來獲取對象ID? – Mundi

+0

@Mundi對不起,該行是錯誤的...我編輯問題 – AppsDev

+0

@Mundi我需要將'mainContext'中的對象傳遞給這個子上下文來執行我的更新。 – AppsDev

回答

0

好吧,至少有1兩件事是錯在你的情況:

調用主線程performBlockAndWait:(通過它傳遞給主隊列)。該文檔說performBlockAndWait:

在接收器的隊列上同步執行給定的塊。

由於這一呼籲的結果,你會得到在主線程死鎖(如你使用dispatch_sync外面的dispatch_async方式

UPDATE:。 的問題不會消失那是因爲你將仍然使用主隊列(這意味着最後的主線程)和主CD上下文(這也意味着主線程)。問題在於,您需要等待主線程等待作業完成相同(主)線 - 只是開箱即用的死鎖

+0

因爲我需要訪問塊內的'objectIDs',這應該是最好的方法:從異步線程調用不同於'privateContext'專用隊列的'handleUpdate',或者使用'dispatch_async'獲取主線程? – AppsDev

+1

我懷疑需要使用同步方法。但是,如果是這樣,只需刪除封閉的dispatch_sync - 但使用NSPrivateQueueConcurrencyType(使用 - (instancetype)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)類型)初始化您的上下文。 –

+0

我使用'dispatch_async'來獲取主隊列,因爲我需要訪問主要上下文的對象,並且mai上下文與主線程相關聯... – AppsDev

0

如果handleUpdate被調用私人隊列如你所說,那麼這是一個典型的僵局。

您在專用隊列上撥打dispatch_sync。這意味着「等到這個返回,然後繼續這個隊列。」然後,在該塊內部,您排隊另一個必須等​​待在專用隊列上運行的塊,直到它結束纔會返回。隊列現在正在等待自己,永遠不會進展。

我懷疑你想dispatch_sync這裏是dispatch_async

+0

但我需要訪問塊內的'objectIDs'數組,不要使用'dispatch_async'會導致問題呢? – AppsDev

+0

從不同於privateContext的私有隊列的異步線程中調用'handleUpdate'會更好嗎,而不是使用'dispatch_async'來獲得主隊列? – AppsDev

+0

我不認爲這裏有一個單一的答案。您需要管理整個應用程序的併發性。確保你已經開始使用Core Data Concurrency部分:https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/CoreData/Concurrency.html。通常情況下,您希望讓Core Data通過'NSPrivateQueueConcurrencyType'處理併發性,而不是試圖強制特定的隊列。 –

0

你有幾個問題。

首先,您正在使用GCD來直接訪問NSMainQueueConcurrency MOC。你應該從來沒有使用除了CoreData同步機制以外的任何訪問CoreData。是的,從主線程訪問NSMainQueueConcurrencyType MOC是安全的。但是,您不應該直接使用GCD ...尤其是dispatch_sync

其次,您使用的是不可重入的dispatch_sync。它可以,也會導致僵局。你幾乎不應該使用這個功能。把它看作一個非常尖銳的工具,用於它是解決非常具體問題的唯一解決方案。

第三,您在子環境上調用performBlockAndWait,不應該這樣做,因爲它可能導致死鎖。一般來說,除非你真的知道你在做什麼,否則你應該避免使用非異步線程模型。

你的代碼應該是更像這樣的東西。每個performBlock調用都會​​將一個塊發送到消息隊列中,該消息隊列將獨立於任何等待的線程進行處理。

- (void)handleUpdate 
{ 
    [self.mainContext performBlock:^{ 
     NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"]; 
     [self.privateContext performBlock: ^{ 
      // Some processing with objectIDs 
     }]; 
    }); 
}