2013-04-21 76 views
2

我有一個經常凍結且永久凍結的應用程序。發生這種情況時,我單擊Xco​​de中的暫停,並在主線程上看到它始終停在執行MOC上的獲取請求的一行代碼上。我還在左側的線程列表中看到輸出__psynch_mutexwait + 17。這使我認爲應用程序正在死鎖或由於某種原因MOC被阻止。追蹤執行executeFetchRequest時導致凍結的塊/死鎖

我的第一本能是我可能在非主線程上執行一個獲取請求,所以我把日誌放在檢查中,但事實並非如此。所有提取都發生在主線程上。

我該如何去追蹤可能阻塞的東西?有沒有更多的東西我應該在堆棧追蹤中尋找?

這是一個問題,我設置在其他線程主線程上獲取的對象的屬性?即,主要獲取objectA,然後將其傳遞給另一個線程,並執行如objectA.someNumber = [NSNumber numberWithInt:2]

回答

0

難道我設置對象的屬性問題上的取主線程在其他線程?即,獲取mainA上的objectA,然後將其傳遞給另一個線程,並執行類似objectA.someNumber = [NSNumber numberWithInt:2]?

是的!我試過這個。

當您在ThreadA中獲取ObjA,然後將它傳遞給ThreadB進行某些操作時,它將陷入死鎖。

+0

是的,因爲發佈這個我意識到託管對象不是線程安全的。使用MOC的'performBlock'方法是解決這個問題的好方法。 – 2013-07-04 19:35:35

0

因爲您的提取請求正在您的應用阻止的主線程上運行,所以它很小心。請記住,主線程是一個串行隊列,並且在您的獲取請求完成之前不會運行其他任何塊(或事件)(即使理論上它可能是因爲您阻塞處於等待狀態)。這解釋了爲什麼當你打破你總是碰到一個_psanch_mutexwait。

您應該在另一個隊列上運行您的讀取請求,並在必要時使用主隊列上的結果。達到此目的的一種方法是使用以下模式:

- (void) fetchRequest1 
{ 
    dispatch_async(not_the_main_queue, ^(void) { 

     // Code the request here. 

     // Then use the result on the main if necessary. 
     dispatch_async(dispatch_get_main_queue(), ^(void) { 
      // Use the result on the main queue. 
     }); 
    }); 
} 

另請注意,通常不需要在主隊列上運行任何內容。事實上,如果您在該線程上儘可能少運行,您的應用程序通常會運行得更順利。當然也有一些事情必須在那裏進行,並在這些情況下,你可以使用下面的模式,以確保它是:

- (void) runBlockOnMainThread:(void(^)(void))block 
{ 
    dispatch_queue_t thisQ = dispatch_get_current_queue(); 
    dispatch_queue_t mainQ = dispatch_get_main_queue(); 

    if (thisQ != mainQ) 
     dispatch_sync(mainQ, block); 
    else 
     block(); 
} 
+0

嗨,只是要清楚我不是說應用程序暫時掛起 - 我的意思是它凍結,並將永遠凍結。除非我錯過了一些東西,看起來這種改變本身並不能解決死鎖問題,它只會簡單地釋放主線程呢? – 2013-04-21 16:03:51

+0

從你提到的內容來看,我假設你的獲取請求是死鎖的原因。我不知道抓取是在等待什麼,但是如果它正在等待的東西也在主線程上運行,那麼它將永遠等待。解決此問題的一種方法是在另一個線程或隊列上運行您的獲取請求。另一個是確定提取請求正在等待什麼並採取行動。 – aLevelOfIndirection 2013-04-21 17:11:40

+0

是的,我很確定這是死鎖的原因。真的,我希望得到一些建議,以追蹤它在等待什麼,以便我可以這樣修復它。我擔心如果我開始創建更多的線程,最終需要管理多個MOC,並且它會很快變得複雜。這是一個公平的假設嗎? – 2013-04-21 18:28:00