问题
I have two tasks that i need to perform in background simultaneously with different thread priorities:
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]; }];
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?
回答1:
I think here you can try by creating only one operation queue and try to setting the priority of each operation according to your need. Thread priority will be more effective and make your mind to think in cleaner way if you use only one queue (after all this is just suggestion.)
- (void)setThreadPriority:(double)priority
The value you specify is mapped to the operating system’s priority values. The specified thread priority is applied to the thread only while the operation’s main method is executing. It is not applied while the operation’s completion block is executing. For a concurrent operation in which you create your own thread, you must set the thread priority yourself in your custom start method and reset the original priority when the operation is finished.
From apple's document.
Operation queues usually provide the threads used to run their operations. In Mac OS X v10.6 and later, operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as concurrent or non-concurrent operations. In iOS 4 and later, operation queues use Grand Central Dispatch to execute operations.
回答2:
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];
来源:https://stackoverflow.com/questions/11533955/two-simultaneous-background-tasks-using-nsoperationqueue