使用NSOperationQueue同时执行两个后台任务

时间:2012-07-18 03:39:03

标签: ios ios5 grand-central-dispatch nsoperationqueue

我有两个任务需要在后台同时执行不同的线程优先级:

  1. 连续收集和处理陀螺仪运动数据(高优先级)

    gyroQueue = [[NSOperationQueue alloc] init];
    
    [self.motionManager startDeviceMotionUpdatesToQueue:gyroQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
        [self processMotion:motion withError:error];
    }];
    
  2. 有时处理图像而不干扰运动更新(转换,裁剪,缩小等= 1-2秒)(优先级非常低)

    imageProcessingQueue = [[NSOperationQueue alloc] init];
    
    [imageProcessingQueue addOperationWithBlock:^{
        [self processImage:[UIImage imageWithData:imageData]];
    }];
    
  3. 编辑:这是我原来的(而不是块操作),它仍然阻止了动作更新:

    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的图像调整大小功能来调整图像大小。有人可以确认它是否是线程安全的吗?

2 个答案:

答案 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];