J'utilise la queue GCD série pour travailler avec le royaume. Les plantages d'application avec Realm accessed from incorrect thread
exception de Realm accessed from incorrect thread
lorsque GCD commence à changer de thread pour la queue. Est-il possible de lier un domaine donné avec un thread en utilisant l'API GCD?
Voici un exemple rapide
self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL); __block RLMRealm *realm = nil; dispatch_async(self.realmQueue, ^{ realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() ssortingngByAppendingPathComponent:@"temp"]]; }); self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.accelerometerUpdateInterval = 0.001; __block int i = 0; __block BOOL shouldBeginWriteTransaction = YES; [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { dispatch_async(self.realmQueue, ^{ if (shouldBeginWriteTransaction) { [realm beginWriteTransaction]; shouldBeginWriteTransaction = NO; } AccelerationEvent *event = [[AccelerationEvent alloc] init]; event.x = accelerometerData.acceleration.x; event.y = accelerometerData.acceleration.x; event.z = accelerometerData.acceleration.y; event.time = [NSDate date]; [realm addObject:event]; if (i % 1000) { dispatch_async(dispatch_get_main_queue(), ^{ self.xLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.x]; self.yLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.y]; self.zLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.z]; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }];
A partir des documents Realm : RLMRealm
objects RLMRealm
ne sont pas thread-safe et ne peuvent pas être partagés entre threads, vous devez donc get une instance RLMRealm
dans chaque thread / dispatch_queue dans lequel vous voulez lire ou écrire.
Également à partir des documents Realm : RLMRealm
objects RLMRealm
sont mis en cache en interne par Realm, et l'appel de cette méthode plusieurs fois sur un seul thread au sein d'une seule itération de la boucle d'exécution renvoie normalement le même object RLMRealm
.
Donc, sachant cela, j'ai modifié votre échantillon de code pour get le RLMRealm
directement à partir du bloc dispatch_async
où il est utilisé, sans encourir de pénalité de performance, car il est mis en cache.
J'ai également remarqué qu'un AccelerationEvent
été passé à travers les threads, ce qui n'est pas autorisé. Cet exemple de code modifié passe donc NSSsortingng
travers les threads.
self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL); self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.accelerometerUpdateInterval = 0.001; __block int i = 0; __block BOOL shouldBeginWriteTransaction = YES; [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { dispatch_async(self.realmQueue, ^{ RLMRealm *realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() ssortingngByAppendingPathComponent:@"temp"]]; if (shouldBeginWriteTransaction) { [realm beginWriteTransaction]; shouldBeginWriteTransaction = NO; } AccelerationEvent *event = [[AccelerationEvent alloc] init]; event.x = accelerometerData.acceleration.x; event.y = accelerometerData.acceleration.x; event.z = accelerometerData.acceleration.y; event.time = [NSDate date]; [realm addObject:event]; if (i % 1000) { NSSsortingng *xSsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.x]; NSSsortingng *ySsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.y]; NSSsortingng *zSsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.z]; dispatch_async(dispatch_get_main_queue(), ^{ self.xLabel.text = xSsortingng; self.yLabel.text = ySsortingng; self.zLabel.text = zSsortingng; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }];
Je n'ai pas exécuté ce code pour confirmer que cela fonctionne, alors laissez-moi savoir si cela ne résout toujours pas le problème.