【问题标题】:Two simultaneous background tasks using NSOperationQueue使用 NSOperationQueue 的两个同时后台任务
【发布时间】:2013-04-08 06:25:00
【问题描述】:

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

  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]];
    }];
    

编辑:这是我最初所拥有的(而不是阻止操作),它仍然阻止运动更新:

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 和veryLow 优先级?

编辑:这个问题仍然悬而未决,我正在使用 Travor Harmon 的图像调整大小功能来调整图像大小。有人可以确认它是否是线程安全的吗?

【问题讨论】:

  • 我仍然没有找到答案,希望有人能提出一些好主意......这对我的应用程序来说不是一个大问题,但缺乏解决方案让我的大脑感到困扰...... . :)

标签: ios ios5 grand-central-dispatch nsoperationqueue


【解决方案1】:

我认为在这里您可以尝试仅创建一个操作队列并尝试根据需要设置每个操作的优先级。如果你只使用一个队列,线程优先级会更有效,让你的思维更清晰(毕竟这只是建议。)

- (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.

【讨论】:

  • 问题是,如何为 startDeviceMotionUpdatesToQueue 方法设置 threadPriority?操作正在由 motionManager 类创建......似乎没有太大的灵活性
  • 是的,但是您可以通过将图像处理的优先级设置为相对于设备运动更新的低优先级来间接解决此问题。
  • 我不确定,但您也可以尝试 NSOperationQueuePriority。我从未使用过此功能,但似乎很有希望。
  • 这是我的初始设置 - 为 imageProcessing 设置低线程优先级,我编辑了我的问题以反映...
  • 这是我对 NSOperationQueue 的理解,但在处理完成之前,动作更新仍然被阻止......唯一不被阻止的方法是,当我将方法包装在 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ // processing image methods here }); 中的 (processImage:) 中但这似乎是错误的,我丢失了队列中 NSOperations 的数量,因为它们立即返回
【解决方案2】:

我已经找到了解决这个问题的方法(或可靠的解决方法):

我没有使用startDeviceMotionUpdatesToQueue 将 deviceMotion 更新路由到队列,而是创建了一个 CADisplayLink 计时器,它不会干扰其他后台队列 - 虽然它与屏幕刷新率匹配,但它本质上具有最高优先级:

[self.motionManager startDeviceMotionUpdates];

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    • 1970-01-01
    相关资源
    最近更新 更多