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

时间:2013-03-08 18:41:06

标签: ios uiimage avfoundation

美好的一天,这就是我想要做的事情:

  • 我有一个使用AVFoundation拍摄图像的照片处理应用
  • 我有一个处理设备位置为60Hz的DeviceMotion队列
  • 拍摄图像时,需要裁剪并保存。 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处理图像时,设备运动更新会在图像裁剪期间被阻止

如果我使用performSelectorInBackground处理图像 - 它可以根据需要工作(没有延迟到DeviceMotion队列)

[self performSelectorInBackground:@selector(processImage:) withObject:[UIImage imageWithData:imageData]];

关于我对背景线程的理解需要更新的任何想法? :)

PS。我之前已经问过这个问题,但它没有任何地方,所以这是重新发布的

1 个答案:

答案 0 :(得分:0)

我找到了解决此问题的解决方案(或可靠的解决方法):

而不是使用startDeviceMotionUpdatesToQueue将deviceMotion更新路由到队列,我创建了一个CADisplayLink计时器并且它不会干扰其他后台队列 - 当它匹配屏幕刷新率时,它的性质给予最高优先级:< / p>

[self.motionManager startDeviceMotionUpdates];

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