2010-11-23 13 views
2

のは、我々が場所のリストを表示する必要があると3つのスレッド上で動作するアプリを持っているとしましょう:(サーバーと 場所を同期するNSManagedObjectContextsとマルチスレッド

  1. メインスレッド
  2. メインスレッドの背景Syncを私はDを持っているすべての3つのスレッドで)
  3. ) バックグラウンドで場所をジオコードする スレッドを(ジオコーディング

編集されたNSManagedObjectContexts(MOC)。ジオコーディングスレッドで緯度/経度情報が追加されている間に、各MOCが基礎データを変更できる場合(主スレッドはお気に入りに場所を追加できますが、背景同期は場所の名前を変更できます)、アプリはNSManagedObjectContextDidSaveNotificationに登録する必要があります1つのMOCが(メインスレッドのMOCにマージされるのではなく)保存された場合は、mergeChangesFromContextDidSaveNotificationを他のスレッドの対応する他のMOCに広げます。今、私はそれをやっている

原因とそれが正しい感じていない:(

を私は自分れるMOCと、現在実行中のスレッドを保存するために使用する辞書を持っている。れるMOCの1がNSManagedObjectContextDidSaveNotificationをポップするたびに私はこの配列をループし、他のすべてのMOC /スレッドにmergeChangesFromContextDidSaveNotificationを送信します。もちろん、オブザーバもNSThreadWillExitNotificationに追加しました。スレッドの1つがなくなると、スレッド/ MOCを配列から削除できます。辞書の操作がロックされています それは私がちょっと邪魔しているところです

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

れるMOC /スレッド辞書をループするとき、私は私を投げ、次の例外を取得:

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

どうやら、これは競合状態によって引き起こされます。辞書をループしている間(私はそのオブジェクト配列を抽出している間だけロックしていました)、出口のスレッドの1つ、したがって参照はもはや有効ではありません。私は、ループ全体の前で辞書ロックを置けば、ループ内のコール

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

は、いくつかのケースでは永遠にかかるのでしかし、私は、デッドロックを取得します(理由はまだ知らない)ため、原因となりますアプリ全体がストールする この場合、waitUntilDone:NOで電話をかけても安全ですか?それはそれを修正するようだ。これで私が誤って開いたパンドラの箱場合、私はちょうど私があなたのアプリケーション構造が危険な状況であなたを入れていると思う....、

よろしく、

セバスチャン

答えて

1

を知りません。競合状態のように、あなたのストレージディクショナリからMOCを削除する前に、いくつかのスレッド "A"が消えてしまうのが私には聞こえます。したがって、スレッド "A"にメッセージを送信しようとすると、それが終了します。代わりに

それをこの方法を考える:

  • 各スレッドは、あなたがスレッドローカルストレージ内で格納できることを、スレッドローカルなオブジェクトを持っている(threadDictionaryを探し、NSThreadのドキュメントを参照してください)
  • このオブジェクトが作成されますスレッドが作業を開始し、指定されたスレッドが使用するMOCを設定します。
  • オブジェクトは保存通知用に登録し、スレッドの有効期間を監視します。
  • スレッドの最後このオブジェクトはdestroyeです作業d。

このようにして、管理オブジェクトコンテキストのライフサイクルをカプセル化し、それを参照する通知メカニズムに直接結び付けます。モニタオブジェクトをスレッドローカルストレージに格納することによって、これらの2つの問題点をスレッドの存続期間に結び付けます。

関連する問題