2011-10-10 1 views
15

私の質問に対する答えは「いいえ」と思っていますが、これについてはまだ混乱しています。だから確認してください。コアデータを複数のスレッドで使用する際には注意が必要であることをすでに知っています。 NSManagedObjectContextオブジェクトはスレッド境界を越えてはいけません。スレッドとCore Dataの両方で初心者であることを喜んで覚えています。コアデータコンテキストを単一のスレッドに限定するのに十分なGCDディスパッチキューです

おそらく、Core Dataを処理するための専用のGCDディスパッチキューを作成することもできます(または、必要に応じて、独自のコアデータコンテキストを持つ複数のディスパッチキューを用意することもできます)。それは簡単だったでしょう。

しかし、今私は、GCDディスパッチキューの大きな利点の1つが、必要に応じて複数のスレッドを管理し、使用することを認識しています。だから、もし私がこの権利を理解していれば、同じディスパッチキューに移り、別のスレッドで実行され、あるスレッドから別のスレッドにコアデータコンテキストを渡す可能性があります。そうですか?

多くの関連する質問と回答、たとえばCore Data and threads/Grand Central Dispatchを読んだことがありますが、やや混乱しています。 GCDキューを使用して、その質問に対する答えは、各スレッドで新しいコンテキストが作成されることを保証しますが、これを行う必要性は指摘しません。もう1つの答えは、コアデータの作業が1つのGCDディスパッチキューに限定されている限り、すべてがOKであることを意味するように見える "com.yourcompany.appname.dataaccessという名前のキューですべてのCoreData作業を実行できます。多分それはそうではありません。

答えて

19

アップデート: @adibがコメントで指摘しているように、シリアル化された管理オブジェクトのコンテキストへのアクセスは、iOS 9とMacOS X 10.11では変更されています。スレッドの閉じ込め戦略であるNSConfinementConcurrencyTypeは現在非推奨になっており、NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyTypeが好ましい。言い換えると、コアデータオブジェクトへの同時アクセスにスレッドの使用を停止し、代わりにGCDの使用を開始します。独自の作成キューではなく、MOCの構成方法に応じて、メインディスパッチキューまたはMOCに関連付けられたキューを使用する必要があります。これは、NSManagedObjectの-performBlock:または-performBlockAndWait:メソッドを使用すると簡単です。


短い答え:管理対象オブジェクトコンテキストにシリアルアクセスを提供することができ、シリアルディスパッチキューを使用して、それはGCDが、実際に複数のスレッドを使用することができるにもかかわらず、「スレッドの閉じ込め」戦略を実施するための許容可能な方法です。

長い答え:

その質問への受け入れ答え、GCDキューを使用して、新しいコンテキストは、各スレッド上で作成されていることを を確保んが、これを行うの 必要性を指摘していません。

あなたが覚えておく必要が大きなものは、あなたが同時にで2つの異なるスレッドから管理対象オブジェクトコンテキストを変更避けなければならないということです。それは文脈を矛盾した状態に置くことができ、何も良いことは起こり得ません。したがって、使用するディスパッチキューの種類が重要です。同時ディスパッチキューでは、複数のタスクを同時に実行することができ、両方が同じコンテキストを使用すると問題になります。一方、シリアルディスパッチキューを使用する場合は、2つ以上のタスクが異なるスレッドで実行される可能性がありますが、タスクは順番に実行され、一度に1つのタスクしか実行されません。これは、少なくともコンテキストの一貫性を維持する限り、同じスレッド上のすべてのタスクを実行するのと非常に似ています。

詳しくは、this questionおよびanswerを参照してください。

これは、Core Dataが常に機能する方法です。コアデータプログラミングガイドのConcurrency with Core Dataセクションには、複数のスレッドで単一のコンテキストを使用することに決めた場合の進め方についてのアドバイスがあります。主に、コンテキストにアクセスするたびにコンテキストをロックすることに非常に注意する必要があることを話します。しかし、すべてのロックのポイントは、2つ以上のスレッドが同時にコンテキストを使用しようとしないようにすることです。シリアライズされたディスパッチ・キューを使用すると同じ目的が達成されます。キュー内の1つのタスクのみが一度に実行されるため、2つ以上のタスクが同時にコンテキストを使用しようとすることはありません。

+1

素晴らしい答えですが、リンクされたスレッドでは、bbumの混乱は、アクセスがシリアル化されていても、MOCオブジェクト自体がスレッドの境界を越えることができないことを暗示しているようです。ベンはこれを具体的に述べているので、私たちは何をする予定ですか? –

+2

@SedateAlien、彼の答えの早い段階で、Benは[documentation](http://tinyurl.com/6dlg75j)の注記を指しています:***注:**スレッド、シリアル操作キュー、または並行処理のためにキューをディスパッチします。簡潔にするために、この記事ではこれらのいずれかを参照するために "スレッド"を使用しています。 "*答えの残りの部分またはドキュメントでは、*スレッド*の代わりに*シリアルディスパッチキュー*を使用することができます。 – Caleb

+0

私は、このシリアルキュー上のMOCを作成する必要がありますか?MOCオブジェクトを作成する場合は、次のようにしてください。オフキューを使用していますが、それを待ち行列に入れても問題ありませんか? –

0

AFAIKあなたは正しいです。 GCDは、キューが実行されているスレッドについて保証しません。キューに送信されたブロックおよび関数呼び出しは、一度に1つずつ実行されますが、Core Dataが現在のスレッドで何かを実行する場合、たとえば、実行ループのソースまたはオブザーバをインストールすると、おそらく意図したとおりに動作しないことがあります。

ただし、Mac OS X 10.7では、メインスレッド、別のスレッド、またはプライベートキューで実行するようにNSManagedObjectContextを設定できます。

関連する問題