2010-11-23 28 views
2

比方說,我們有需要顯示的地點列表,並可以運行在3個線程的應用程序:NSManagedObjectContexts和多線程

  1. 主線
  2. 主線程後臺同步(同步 地方與服務器)
  3. 天氣預報 線程(地理編碼在 背景的地方)

在所有3個線程我有d編號爲NSManagedObjectContexts(MOCs)。如果每個MOC都可以更改底層數據(主線程可以將該地點添加到收藏夾中,而後臺同步可以更改該地點的名稱,而地址解碼線程添加緯度/經度信息),則應用程序必須註冊NSManagedObjectContextDidSaveNotification每個線程,然後散佈mergeChangesFromContextDidSaveNotification到其他線程中的相應的其他線程,如果一個MOC得到保存(不只是合併到主線程的MOC),正確的???

因爲現在我這樣做,並沒有覺得不對勁:(

我有一本字典,我使用到當前正在運行的線程保存它們的MOCS。每當MOCS的一個彈出NSManagedObjectContextDidSaveNotification我循環遍歷這個數組併發送mergeChangesFromContextDidSaveNotification到所有其他的MOC/Threads。當然,我還在NSThreadWillExitNotification上添加了一個觀察者,這樣當其中一個線程用完時,我可以從數組中移除Thread/MOC。字典被鎖定 這就是我現在有點被卡住的情況,有時當我打電話時

[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) 
onThread:thread 
withObject:notification 
waitUntilDone:YES]; 
通過MOCS /線程詞典循環時

,我得到下面的異常扔給我:

[NSManagedObjectContext performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform 

顯然,這是由競爭條件引起的。在循環字典時(我只在提取其對象數組的同時將其鎖定),退出時的線程之一,因此引用無效。但是,如果我把字典鎖在整個循環的面前,我得到了僵局,因爲呼叫

[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) 
onThread:thread 
withObject:notification 
waitUntilDone:YES]; 

內環路在某些情況下需要永遠(不知道爲什麼還沒有),從而導致整個應用程序停止。 在這種情況下與waitUntilDone:NO打電話安全嗎?因爲這似乎解決了它。我只是不知道,如果我不小心打開潘多拉這個箱子....

問候,

塞巴斯蒂安

回答

1

我覺得你的應用程序結構,把你在危險的情況。在我看來,競爭條件是某些線程「A」會在您從存儲字典中刪除MOC之前消失。因此,您嘗試在線程「A」上發送一條消息並將其終止。

反而覺得它是這樣的:

  • 每個線程都有一個線程局部對象,您可以在線程本地存儲中存儲(見NSThread文檔,尋找threadDictionary)
  • 創建該對象當你的線程開始這樣做的時候,並設置一個給定的線程使用的MOC
  • 該對象還註冊保存通知,並監視它們的線程工作的生命週期
  • 在線程的末尾工作這個對象是破壞者d。

這種方式可以封裝託管對象上下文的生命週期,並將其直接綁定到將引用它的通知機制。通過將監視器對象存儲在線程本地存儲中,您還可以將這兩個關注點綁定到線程的生命週期中。