2

場所のリストを表示する必要があり、3 つのスレッドで実行されるアプリがあるとします。

  1. メインスレッド
  2. Main Thread Background Sync (場所をサーバーと同期するため)
  3. ジオコーディング スレッド (バックグラウンドで場所をジオコーディングするため)

私が専用にした3つのスレッドすべてでNSManagedObjectContexts(MOC)。各 MOC が基礎となるデータを変更できる場合 (たとえば、メイン スレッドは場所をお気に入りに追加でき、バックグラウンド同期は場所の名前を変更でき、ジオコーディング スレッドは緯度/経度情報を追加できます)、アプリはNSManagedObjectContextDidSaveNotificationそれぞれに登録する必要があります。スレッドをmergeChangesFromContextDidSaveNotification作成し、1 つの MOC が保存された場合 (メイン スレッドの MOC にマージするだけでなく)、他のスレッド内の対応する他の MOC に展開します。

今、私はそれをやっていますが、それは正しくないと感じています:(

現在実行中のスレッドを MOC とともに保存するために使用する辞書があります。MOC の 1 つがポップするたびに、NSManagedObjectContextDidSaveNotificationこの配列を I ループし、mergeChangesFromContextDidSaveNotification他のすべての MOC/スレッドに送信します。もちろん、NSThreadWillExitNotificationスレッドの 1 つがなくなったときに配列から Thread/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この場合、呼び出しを行うのは安全ですか? それで治りそうだから。これでパンドラの箱を誤って開けてしまったら…。

よろしく、

セバスチャン

4

1 に答える 1

1

アプリケーション構造が危険な状況に陥っていると思います。ストレージ ディクショナリから MOC を削除する前に、一部のスレッド "A" が消えるという競合状態のように思えます。したがって、スレッド「A」でメッセージを送信しようとすると、スレッドは終了します。

代わりに、次のように考えてください。

  • 各スレッドには、スレッド ローカル ストレージ内に格納できるスレッド ローカル オブジェクトがあります (NSThread ドキュメントを参照し、threadDictionary を探します)。
  • このオブジェクトは、スレッドが作業を開始したときに作成され、特定のスレッドで使用される MOC を設定します
  • オブジェクトは保存通知も登録し、スレッド作業の存続期間を監視します。
  • スレッド作業の最後に、このオブジェクトは破棄されます。

このようにして、管理対象オブジェクト コンテキストのライフサイクルをカプセル化し、それを参照する通知メカニズムに直接関連付けます。モニター・オブジェクトをスレッド・ローカル・ストレージに保管することにより、これら 2 つの懸念事項をスレッドの存続期間に関連付けることもできます。

于 2010-11-23T23:14:54.923 に答える