Reino acceder desde incorrecto hilo

Estoy usando la serie MCD cola para trabajar con el reino. La aplicación se bloquea con Realm accessed from incorrect thread excepción cuando MCD empieza a cambiar los hilos de la cola. Es allí cualquier manera de enlazar reinado dado con un hilo usando el MCD API?

Aquí está un ejemplo rápido

self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL);

__block RLMRealm *realm = nil;
dispatch_async(self.realmQueue, ^{
    realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"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 = [NSString stringWithFormat:@"%f", event.x];
                self.yLabel.text = [NSString stringWithFormat:@"%f", event.y];
                self.zLabel.text = [NSString stringWithFormat:@"%f", event.z];
            });
        }

        if (i % 10000 == 0) {
            NSDate *startDate = [NSDate date];
            [realm commitWriteTransaction];
            NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]);
            shouldBeginWriteTransaction = YES;
        }

        i++;
    });
}];
InformationsquelleAutor Maxim | 2014-09-04

1 Kommentar

  1. 35

    De Reino docs: RLMRealm objetos no son seguros para subprocesos y no puede ser compartida a través de los subprocesos, por lo que usted debe conseguir una RLMRealm instancia en cada hilo/dispatch_queue en la que desea leer o escribir.

    También desde el Ámbito docs: RLMRealm objetos se almacenan internamente por el Reino, y la llamada a este método varias veces en un mismo hilo dentro de una sola iteración de la ejecución del bucle normalmente devuelven el mismo RLMRealm objeto.

    Así que sabiendo esto, he modificado el código de la muestra para obtener el RLMRealm directamente desde el dispatch_async bloque donde se utiliza, sin incurrir en una penalización de rendimiento, ya que se almacena en caché.

    También me di cuenta de que un AccelerationEvent fue aprobada a través de los subprocesos, que tampoco es permitido. Así que esta modificado el código de la muestra pasa NSStrings a través de los hilos en su lugar.

    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() stringByAppendingPathComponent:@"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) {
                NSString *xString = [NSString stringWithFormat:@"%f", event.x];
                NSString *yString = [NSString stringWithFormat:@"%f", event.y];
                NSString *zString = [NSString stringWithFormat:@"%f", event.z];
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.xLabel.text = xString;
                    self.yLabel.text = yString;
                    self.zLabel.text = zString;
                });
            }
    
            if (i % 10000 == 0) {
                NSDate *startDate = [NSDate date];
                [realm commitWriteTransaction];
                NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]);
                shouldBeginWriteTransaction = YES;
            }
    
            i++;
        });
    }];

    No he de ejecutar este código para confirmar que funciona, así, hágamelo saber si esto no resuelve el problema.

    • de lo que usted dice, yo pensaba que sólo RLMRealm no es thread-safe, resulta que todos los RLMObject subclases tengo de ese reino no son seguros para subprocesos, demasiado
    • Desde el Ámbito de la documentación: «sólo se puede utilizar un objeto en el hilo que se ha creado, y no puede acceder a su ivars directamente para cualquier conservan las propiedades.» reino.io/docs/objc/última/#modelos

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea