具有不同优先级的多个操作队列
Posted
技术标签:
【中文标题】具有不同优先级的多个操作队列【英文标题】:Multiple Operation Queues with Different priorities 【发布时间】:2013-03-08 18:41:05 【问题描述】:美好的一天,这就是我想要做的:
我有一个使用 AVFoundation 拍摄图像的照片处理应用程序 我有一个 DeviceMotion 队列,它以 60Hz 的频率处理设备位置 拍摄图像时,需要裁剪并保存。 DeviceMotion 需要持续运行并及时更新界面我看到的是:在图像裁剪期间,来自 DeviceMotion 队列的接口更新被冻结。
这就是我开始更新 DeviceMotion 的方式:
self.motionManager.deviceMotionUpdateInterval = 1.0f/60.0f;
gyroQueue = [[NSOperationQueue alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:gyroQueue withHandler:^(CMDeviceMotion *motion, NSError *error)
[NSThread setThreadPriority:1.0];
[self processMotion:motion withError:error];
];
当图像从 AVFoundation 返回时,它被添加到队列中进行处理:
imageProcessingQueue = [[NSOperationQueue alloc] init];
[imageProcessingQueue setName:@"ImageProcessingQueue"];
[imageProcessingQueue setMaxConcurrentOperationCount:1];
//[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:NSOperationQueuePriorityVeryLow];
[imageProcessingQueue addOperation:operation];
以及处理图像的方法:
- (void)processImage:(UIImage*)image
CGSize cropImageSize = CGSizeMake(640,960);
UIImage *croppedImage = [image resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:cropImageSize interpolationQuality:kImageCropInterpolationQuality];
NSData *compressedImageData = UIImageJPEGRepresentation(croppedImage, kJpegCompression);
[self.doc addPhoto:compressedImageData];
问题是:
使用 NSOperationQueue 处理图像时,在图像裁剪期间会阻止 devicemotion 更新如果我使用 performSelectorInBackground 处理图像 - 它会按需要工作(不会延迟 DeviceMotion 队列)
[self performSelectorInBackground:@selector(processImage:) withObject:[UIImage imageWithData:imageData]];
关于我对后台线程的理解需要更新的任何想法? :)
PS。这个问题我之前也问过,但是没有找到,所以重新发帖
【问题讨论】:
你在哪里设置queuePriority
你的操作队列?
我在 NSInvocationOperation 上设置 queuePriority,请参阅上面的更新代码...
为什么将优先级设置为0.0
而不是NSOperationQueuePriorityVeryHigh
或NSOperationQueuePriorityVeryHigh
之一? 0
(不是浮点数)是标准优先级。
刚刚尝试将 queuePriority 设置为 NSOperationQueuePriorityVeryLow,没有任何更改。我怀疑它与 threadPriority 有更多关系,因为 DeviceMotion 更新将进入另一个队列。对于 threadPriorty 0.0 是最低的,这是我进行图像处理所需要的。
您对[NSThread setThreadPriority:1.0]
的调用至少应该与将线程重置为其原始优先级的类似调用配对。你不拥有线程,NSOperationQueue/GCD 拥有。我最好的猜测是设备运动更新被发送到主队列,然后从那里转发到您指定的队列。
【参考方案1】:
我已经找到了解决这个问题的方法(或可靠的解决方法):
我没有使用startDeviceMotionUpdatesToQueue
将 deviceMotion 更新路由到队列,而是创建了一个 CADisplayLink 计时器,它不会干扰其他后台队列 - 虽然它与屏幕刷新率匹配,但它本质上具有最高优先级:
[self.motionManager startDeviceMotionUpdates];
gyroTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(processMotion)];
[gyroTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
【讨论】:
以上是关于具有不同优先级的多个操作队列的主要内容,如果未能解决你的问题,请参考以下文章