3

我正在执行以下方法:

运动处理器.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

在当前的实施中?谢谢!

4

2 回答 2

5

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

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

  1. 一个后台线程,但在主队列上

不可能 - NSOperation 的 mainQueue 始终与 mainThread 相关联。

  1. 一个后台线程,但在当前队列中

当您创建一个 NSOperationQueue 并向其中添加 NSOperations 时,它们会在队列管理的后台线程上运行。任何给定的操作都可以查询它在哪个线程上,并且该线程在运行时不会改变。也就是说,该队列上的第二个操作可能会在不同的线程上运行。

  1. 主线程但在主队列上

见 1)

  1. 主线程但在当前队列中

如果您将操作排队到 mainQueue(我们知道它总是在 mainThread 上),并且您请求 currentQueue,它将返回 mainQueue:

[NSOperationQueue currentQueue] == [NSOperationQueue mainQueue];
于 2012-08-28T13:23:47.493 回答
4

您将队列与线程混淆了。尤其是由于NSPertionQueue已经被重写为使用GCD,队列和特定线程之间几乎没有联系(除了主线程的特殊情况)。

操作/块/任务——无论你想怎么称呼它们——都被插入到队列中,“工作线程”将它们拉下来并执行它们。您几乎无法控制哪个确切的线程将执行该工作——除了主队列。 请注意,这并不完全正确,因为它是一种简化,但它是正确的,除非您正在做一些非常高级和具体的事情。

因此,您的 4 个场景都没有任何意义,因为例如,您不能在“后台线程但在主队列上”运行某些东西。

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

为了使事情变得有些复杂,您startAccelerationUpdates通过调用来调用该方法performSelectorInBackground。同样,您不知道实际调用哪个线程startAccelerationUpdates,但它不会是主线程。

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

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

因为处理的事件可能会以很高的速率到达,所以不建议使用主操作队列。

不幸的是,你的陈述

更有趣的是,当我再次在后台线程上调用上述方法时,但这次使用当前队列,我没有得到任何更新。

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

我将重点介绍您对the current Queue.

我假设你的意思是你[NSOperationQueue mainQueue][NSOperationQueue currentQueue].

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

当前队列

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

+(id)当前队列

返回值

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

讨论

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

请注意讨论部分。如果您在没有运行从 调用的操作时调用它NSOperationQueue,您将得到nil这意味着将没有队列可以放置您的处理程序。所以,你将一无所获。

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

祝你好运!

于 2012-08-28T13:28:07.507 回答