Search code examples
iosios5grand-central-dispatchnsoperationqueue

Two simultaneous background tasks using NSOperationQueue


I have two tasks that i need to perform in background simultaneously with different thread priorities:

  1. continuously gather and process gyro motion data (high priority)

    gyroQueue = [[NSOperationQueue alloc] init];
    
    [self.motionManager startDeviceMotionUpdatesToQueue:gyroQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
        [self processMotion:motion withError:error];
    }];
    
  2. Sometimes process images without interfering with motion updates (convert, crop, sesize, etc = 1-2sec) (very low priority)

    imageProcessingQueue = [[NSOperationQueue alloc] init];
    
    [imageProcessingQueue addOperationWithBlock:^{
        [self processImage:[UIImage imageWithData:imageData]];
    }];
    

EDIT: this is what I had in place originally (instead of block operation), and it is still blocking the motion updates:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(processImage:) object:[UIImage imageWithData:imageData]];
[operation setThreadPriority:0.0];
[operation setQueuePriority:0.0];
[imageProcessingQueue addOperation:operation];

It seems as both of these tasks are being executed on the same background thread (due to NSOperationQueue nature?), and processing of an image blocks the gyroQueue updates until it's done, which is what i am trying to avoid.

How can I spawn two separate threads using NSOperationQueue, and assign veryHigh & veryLow priorities accordingly?

EDIT: this question is still open, i am using Travor Harmon's image resize functions for image resize. Can someone confirm if it's thread safe?


Solution

  • i have found a solution (or solid workaround) for this issue:

    instead of routing deviceMotion updates to the queue using startDeviceMotionUpdatesToQueue, i have created a CADisplayLink timer and it is not interfering with other background queues - while it is matching screen refresh rate it's given highest priority by it's nature:

    [self.motionManager startDeviceMotionUpdates];
    
    gyroTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(processMotion)];
    [gyroTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];