4

コアデータを使用するマルチスレッドアプリケーションがあります。私は起動時にたくさんのクラッシュが発生していて、さまざまな奇妙なエラーメッセージが表示されています。しかし、時々それはうまく動作します!自分のiPhone4でクラッシュを見たことはありませんが、他のデバイスでクラッシュします。私は問題を理解したと思うが、それをどのように最善に解決するかはわからない。コアデータ - 起動時のマルチスレッド競合状態

アプリが起動すると、GCDを使ってウェブからデータをダウンロードし、バックグラウンドスレッドのコアデータを更新します。メインスレッドでは、テーブルビューの設定を続け、これらのコマンドの1つがNSManagedObjectContextゲッターをトリガーします。私はかなり多くの標準テンプレートコードを使用しています。これが初めて実行されるときに、通常の遅延インスタンスコードによってNSPersistentStoreCoordinatorが作成されます。

しかし、バックグラウンドスレッドはそれ自身のために新しいNSManagedObjectContextを作成しています。これは、次のようにNSPersistentStoreCoordinatorを取得しています

// Create a new NSManagedObjectContext for this thread 
    NSManagedObjectContext *threadContext = nil; 
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) 
    { 
     threadContext = [[NSManagedObjectContext alloc] init]; 
     [threadContext setPersistentStoreCoordinator:coordinator]; 
     NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType]; 
     [threadContext setMergePolicy:mergePolicy]; 
    } else { 
     NSLog(@"Error - No NSPersistentStoreCoordinator"); 
    } 

私はその問題は、両方のスレッドが同時にNSPersistentStoreCoordinatorコードになっているということである90%確信しています。両方のスレッドはオブジェクトがnilだと信じて、オブジェクトを作成します。これは、ivarが突然間違った場所を指しているため、最初のスレッドがそこに到達する問題を引き起こします。その時点で悪いことが起こります!

これを解決するにはどうすればよいですか?私は一時的にバックグラウンドスレッドにsleep(1)を追加して問題を解決しました:)しかし、これは実際には最高の解決策ではないかと思います!私はNSPersistentStoreCoordinatorのプロパティをアトミックに変更しようとしましたが、これは役に立ちませんでした。ミューテックスをロックするには、標準ゲッターのそれぞれを@synchroniseにラップする必要がありますか?私はまだこれを試す時間がありませんでしたが、両方のスレッドが同じコードを実行するのを止めるべきです。それとも良い方法がありますか?

思考?

おかげクレイグ

======================================

情報については、私が見たいくつかのエラーとクラッシュがあります。これらはかなり無作為ですが、他の人が将来この投稿を見つけるのを助けるかもしれません。

2012-01-18 22:19:57.586 CBF [10468:11d03は] - [NSSQLModel _addPersistentStore:識別子:]:認識されていないセレクタはインスタンスに0x6b80390

2012-01-18午前22時19分に送信しました:57.595 CBF [10468:11d03] *起因 キャッチされない例外 'NSInvalidArgumentException' にアプリの終了は、理由: -

2012-01-を '[NSSQLModel _addPersistentStore:識別子:]未認識セレクタインスタンス0x6b80390に送ら' 19 16:58:06.671 CBF [11738:fe03] - [__ NSCFDictionary _hasPrecomputedKeyOrder]:45:31.174 CBF [16911を:未認識セレクタは

2012-01-25 21インスタンス0x6d55040に送信1310B] - [__ NSArrayM _addPersistentStore:識別子:]:認識されていないセレクタはインスタンスに送信0x6d59370

2012-01-25 21:45:31。175 CBF [16911:1310B]アプリを終了*起因する キャッチされない例外 'NSInvalidArgumentException'、理由: ' - [__ NSArrayM _addPersistentStore:識別子:]:認識されていないセレクタはインスタンス0x6d59370に送信された'

答えて

4

理由だけではなく、怠惰なインスタンス化を削除し、代わりにアプリケーションが起動するとすぐにコーディネータを作成しますか?

+1

ありがとうございました。あなたは、それがとても分かりました。実際には、私は怠惰なインスタンス化を残すことができますが、私は具体的にNSManagedObjectContextゲッターを呼び出して、セットアッププロセス全体を蹴飛ばし、結果を遠ざけるようにしてください。他のコアデータより先にこれを行うと、すべてがOKになります。どうもありがとう。 –

+0

こんにちはクレイグ、私は解決策を理解できませんでしたあなたはより詳細に説明することができますコアデータを同期すると同様の問題に直面していると特定のレコードを表示しようとすると、特定のレコードを削除しようとしました –

+1

@iphonegeek同時。これは通常はOKですが、初めて使用されるときは 'if blah = nil then alloc/init'と言う通常の遅延インスタンス化コードがあります。問題は2番目のスレッドがメソッドに到達し、ivarsがまだnilだったことです最初のスレッドによって行われたalloc/initが完了していないためです。解決策は、第2スレッドをフォークする前にメインスレッドに次の行を追加することでした: 'NSManagedObjectContext * unused __attribute __((未使用))= [self managedObjectContext];'これはすべてが作成されることを保証します。 –