IOS5で次のコードを同期しようとしています:
これは(簡略化された)コードです:
- (void)insideSomeMethod
{
[SomeHTTPRequest withCompletionHandler:
^(id retrievedData)
{
if(!retrievedData)
{
handler(nil);
}
// Populate CoreData model with retrieved Data...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
handler(aCoreDataNSManagedObject);
[self shouldCommitChangesToModel];
}];
}
- (void)shouldCommitChangesToModel
{
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
}
しかし、何が起こっているのかというと、バリアベースの保存ブロックは常に画像読み込みブロックの前に実行されます。あれは、
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
前に実行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
したがって、明らかに、バリアの前に画像読み込みブロックを実際にディスパッチしているわけではありません。そうしないと、バリアは画像読み込みブロックが完了するまで待機してから実行されます(これは私の意図でした)。
私は何が間違っているのですか?画像読み込みブロックがバリアブロックの前にキューに入れられていることを確認するにはどうすればよいですか?
一見したところ、問題は、グローバル同時キューにバリアブロックをディスパッチしていることである可能性があります。バリアブロックは、独自のカスタム並行キューでのみ使用できます。 dispatch_barrier_asyncのGCDドキュメントによると、ブロックをグローバルキューにディスパッチすると、通常のdispatch_async呼び出しのように動作します。
Mike Ashは、GCDバリアブロックに関する優れたブログ投稿をしています: http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html
幸運を
T
ADCドキュメントのようにグローバルキューにディスパッチするのではなく、独自のキューを作成する必要があります
指定するキューは、dispatch_queue_create関数を使用して自分で作成する並行キューである必要があります。この関数に渡すキューがシリアルキューまたはグローバル同時キューの1つである場合、この関数はdispatch_async関数のように動作します。
独自のGCDキューを大量に作成できます。 gcdキューは非常に小さく、問題なく大量に作成できます。それらを使い終わったら、それらを解放する必要があります。
パーティーに少し遅れましたが、次回はdispatch_group
sを活用してみてください。 http://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2
あなたが解決しようとしているように見えるものについては、dispatch_barrier_async
は最善の解決策ではないかもしれません。並行性プログラミングガイドの スレッドからの移行 セクションをご覧ください。独自のシリアルキューでdispatch_sync
を使用するだけで、同期の問題が解決する場合があります。または、NSOperationとNSOperationQueueを使用することもできます。 GCDとは異なり、NSOperationを使用すると、依存関係を簡単に管理できます(GCDを使用して管理できますが、高速になる可能性があります)。