0

私はマルチスレッドを使用してデータを取得し、解析し、オブジェクトを作成して保存しています。そして、これがすべて完了した後、ウィンドウを表示したいと思います。しかし今、私には2つの問題があります。

  • デッドロックがあります
  • 私のバリアはバリアとして機能しません。

デッドロックは、一度に複数のスレッドでmanagedObjectContextを更新しているためだと思います。

  1. そこで、ManagedObjectContextをConcurrencyTypeで変更しました。

    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
  2. そして、並行性キューのimportContextを作成し、parentContextを割り当てました。

    NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    importContext.parentContext = self.managedObjectContext;
    
  3. そして、importContextのperformBlockに操作を配置します。

    [importContext performBlock:^{
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodAWithContext:importContext];
      });
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodBWithContext:importContext];
      });
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodCWithContext:importContext];
      });
    
    
      dispatch_barrier_async(backgroundQueueM, ^{
      // create barrier to wait for the first 3 threads to be completed.
       dispatch_async(dispatch_get_main_queue(), ^{
    
        // Save the data from the importContext tot the main context on the main queue
        NSError *importError = nil;
        [importContext save:&importError];
        [importContext.parentContext performBlock:^{
           NSError *parentError = nil;
           [importContext.parentContext save:&parentError];
        }];
    
       [self.window makeKeyAndVisible];
    
       });
      });
    }];
    

アプローチ1:各メソッドで、オブジェクトのサブセットを選択し、これらを削除してから、新しいオブジェクトを作成して保存します。(削除は、フェッチを実行して、作成されるすべてのオブジェクトの存在を確認するよりも速いと思いました)。したがって、メソッドAIで、すべてのAObjectを選択し、それらを削除して、新しいAObjectを作成します。メソッドBIで、すべてのBObjectを選択し、それらを削除して、新しいBObjectを作成します。メソッドCIで、すべてのCObjectを選択し、それらを削除して、新しいCObjectを作成します。

しかし、「NSManagedObjectContextは他のコンテキストのオブジェクトを削除できません」というエラーが表示されます。

したがって、アプローチ2:削除を削除しました。しかし今、私はさまざまな異なるエラーを受け取ります.....そしてバリアは他のスレッドが実行されるのを待ちません。

Q1:何が間違っているのですか?

Q2:3つのスレッドが完了するのを待つためのバリアを取得するにはどうすればよいですか?

Q3:さまざまなスレッドのオブジェクトを削除/パージするにはどうすればよいですか?

(Appleのリリースノートとドキュメントを読みましたが、マルチスレッドとmanagedContextの組み合わせに関する明確な説明が見つかりません。)

4

1 に答える 1

3

dispatch_async内で呼び出すことはできませんperformBlock。タイプの管理対象オブジェクトコンテキストにはNSPrivateQueueConcurrencyType、操作を実行するための独自のディスパッチキューがあります。

複数の操作を別のディスパッチキューに移動して並行して実行しようとしましたが、それは不可能です。

本当に複数の操作を並行して実行する必要がある場合は、操作ごとにプライベート同時実行タイプMOCを作成する必要があります。

追加した:

すべての操作が完了するのを待つ方法はいくつかあります。

  • それぞれの最後でカウンターをインクリメントし、そのperformBlock:値が(この例では)3であるかどうかを確認できます。
  • dispatch_semaphore_create初期値がゼロの操作ごとにセマフォ()を作成し、すべてのセマフォ( dispatch_semaphore_wait)を待って、それぞれの終わりにセマフォに信号を送ることができますperformBlock
  • そして、私はこれを行うためのより良い/よりエレガントな/より洗練された方法があると確信しています。

しかし、私があなたの質問を読み直していると、あなた

[self.window makeKeyAndVisible];

すべてのCoreDataフェッチ操作が完了するまで。データのインポートが完了するまでユーザーには何も表示されないため、これは適切な設計ではありません。

より良い設計は、初期ビューをすぐに表示し、バックグラウンド操作がデータをフェッチしたときにそのビューを更新することです。

于 2012-08-18T10:59:27.423 に答える