我有两个任务需要在后台同时执行不同的线程优先级:
连续收集和处理陀螺仪运动数据(高优先级)
gyroQueue = [[NSOperationQueue alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:gyroQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
[self processMotion:motion withError:error];
}];
有时处理图像而不干扰运动更新(转换,裁剪,缩小等= 1-2秒)(优先级非常低)
imageProcessingQueue = [[NSOperationQueue alloc] init];
[imageProcessingQueue addOperationWithBlock:^{
[self processImage:[UIImage imageWithData:imageData]];
}];
编辑:这是我原来的(而不是块操作),它仍然阻止了动作更新:
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(processImage:) object:[UIImage imageWithData:imageData]];
[operation setThreadPriority:0.0];
[operation setQueuePriority:0.0];
[imageProcessingQueue addOperation:operation];
似乎这两个任务都在同一个后台线程上执行(由于NSOperationQueue性质?),并且图像处理会阻止gyroQueue更新,直到完成为止,这正是我想要避免的。
如何使用NSOperationQueue生成两个单独的线程,并指定veryHigh&相应的优先级如何?
编辑:这个问题仍然存在,我正在使用Travor Harmon的图像调整大小功能来调整图像大小。有人可以确认它是否是线程安全的吗?答案 0 :(得分:0)
我想在这里你可以尝试只创建一个操作队列,并尝试根据需要设置每个操作的优先级。线程优先级将更有效,如果您只使用一个队列,那么让您的思维更清晰(毕竟这只是建议。)
- (void)setThreadPriority:(double)priority
您指定的值将映射到操作系统的优先级值。仅当操作的main方法正在执行时,指定的线程优先级才应用于线程。在操作的完成块执行时不应用它。对于您在其中创建自己的线程的并发操作,您必须在自定义启动方法中自己设置线程优先级,并在操作完成时重置原始优先级。
来自苹果的文件。
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.
答案 1 :(得分:0)
我找到了解决此问题的解决方案(或可靠的解决方法):
而不是使用startDeviceMotionUpdatesToQueue
将deviceMotion更新路由到队列,我创建了一个CADisplayLink计时器并且它不会干扰其他后台队列 - 当它匹配屏幕刷新率时,它的性质给予最高优先级:< / p>
[self.motionManager startDeviceMotionUpdates];
gyroTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(processMotion)];
[gyroTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];