主队列/当前队列之间的差异&在这种情况下主线程/后台线程?

时间:2012-08-28 12:00:52

标签: objective-c ios multithreading queue

我正在执行以下方法:

MotionHandler.m

-(void)startAccelerationUpdates
{
    [motionManagerstartDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMDeviceMotion *motion, NSError *error){.....}
}

在后台线程上,如下所示:

[currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];

但是上面的方法使用main Queue(在主线程上)来执行必要的更新,即使我在后台线程上调用它。所以在后台线程上执行加速更新或者在主线上,我很困惑..?

更有趣的是,当我再次在后台线程上调用上述方法时,但这次使用current Queue,我得不到更新。有人可以解释一下运行之间的区别:

 1. a background thread but on the main queue

 2. a background thread but on the current queue 

 3. the main thread but on the main queue  

 4. the main thread but on the current queue

在当前的实施中?谢谢!

2 个答案:

答案 0 :(得分:5)

我会试一试。首先,在没有被NSOperationQueue类引用告知的情况下,我们无法推断出'mainQueue'将在哪个线程上运行。阅读它我们看到实际上队列在mainThread(UI使用的那个)上运行其操作,因此您可以更新发布到该队列的操作中的UI。虽然它没有说明,但这些操作必须是串行的,因为它们是由runLoop执行的(它们可能也会被抢占,而不是100%肯定)。

currentQueue的目的是使运行操作可以确定它们所在的队列,因此它们可以在该队列上对新操作进行排队。

  1. 后台线程但在主队列上
  2. 不可能 - NSOperation的mainQueue始终与mainThread相关联。

    1. 后台线程,但在当前队列上
    2. 当您创建NSOperationQueue并向其添加NSOperations时,这些将在队列管理的后台线程上运行。任何给定的操作都可以查询它所在的线程,并且该线程在运行时不会更改。也就是说,该队列上的第二个操作可能会在另一个线程上运行。

      1. 主线程但在主队列上
      2. 见1)

        1. 主线程但在当前队列上
        2. 如果将操作排队到mainQueue(我们知道它总是在mainThread上),并且你要求currentQueue,它将返回mainQueue:

          [NSOperationQueue currentQueue] == [NSOperationQueue mainQueue];
          

答案 1 :(得分:4)

您将队列与线程混淆。特别是因为NSOpertionQueue已经被重写为使用GCD,所以队列和特定线程之间几乎没有连接(除了主线程的特殊情况)。

操作/块/任务 - 无论你想要什么 - 都要插入队列,“工作线程”将它们拉出来并执行它们。除了主队列之外,你无法控制哪个确切的线程要做什么工作。 注意,这不完全正确,因为它是一种简化,但除非你做的事情非常先进和具体,否则它是真的。

所以,你的4个场景中没有一个甚至是有意义的,因为你不能,例如,在“后台线程上但在主队列上运行”。

现在,您的方法startAccelerationUpdates专门告诉CMMotionManager将您的处理程序放在主队列上。因此,当调用startAccelerationUpdates时,它会在它运行的任何线程中运行,但它会调度在主线程上执行的处理程序。

要使事情有些复杂,您可以通过调用startAccelerationUpdates来调用performSelectorInBackground方法。同样,你不知道哪个线程实际上会调用startAccelerationUpdates,但它不会是主线程。

但是,在你的情况下,所有线程正在做的是调用startAccelerationUpdates,它正在开始运动更新,并告诉它们在主线程上处理(通过主队列)。

现在,这里有一些东西可以阻止你直接从文档中使用主队列来处理动作事件......

  

由于处理的事件可能以高速率到达,因此不建议使用主操作队列。

不幸的是,你的陈述

  

更有趣的是,当我打开上面的方法时   后台线程再次,但这次使用当前的队列,我得到   没有更新。

没有提供足够的信息来确定您尝试了什么,您是如何尝试的,或者您认为它不起作用的原因。所以,我会猜测......这可能是错的。

我将使用the current Queue

我认为您的意思是用[NSOperationQueue mainQueue]替换[NSOperationQueue currentQueue]

好吧,让我们看看它的作用。您将使用“其他”队列而不是使用主队列。哪一个?好吧,让我们来看看文档:

  

<强> currentQueue

     

返回启动当前的操作队列   操作

     

+(id)currentQueue

     

返回值

     

启动操作的操作队列,如果无法确定队列,则为nil。

     

<强>讨论

     

您可以在正在运行的操作中使用此方法   object获取对启动它的操作队列的引用。   从正在运行的操作的上下文之外调用此方法   通常导致返回nil。

请注意讨论部分。如果在未运行从NSOperationQueue调用的操作时调用此方法,则将获得nil,这意味着将没有可放置处理程序的队列。所以,你什么也得不到。

如果要使用主队列以外的NSOperationQueue,则必须指定要使用的队列。所以,如果这是您想要的路线,只需创建自己的操作队列来处理动作事件,然后关闭!

祝你好运!