具有不同优先级的多个操作队列

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 而不是NSOperationQueuePriorityVeryHighNSOperationQueuePriorityVeryHigh 之一? 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];

【讨论】:

以上是关于具有不同优先级的多个操作队列的主要内容,如果未能解决你的问题,请参考以下文章

将多个项目添加到具有固定大小数组的优先级队列时出错

C++优先队列(priority_queue)

优先队列priority_queue

优先级队列的总结

POSIX消息队列 - mq_send线程唤醒命令

c++优先队列(priority_queue)用法详解