Objective c 主队列/当前队列之间的差异&;本例中的主线程/背景线程?

Objective c 主队列/当前队列之间的差异&;本例中的主线程/背景线程?,objective-c,ios,multithreading,queue,Objective C,Ios,Multithreading,Queue,我正在执行以下方法: MotionHandler.m -(void)startAccelerationUpdates { [motionManagerstartDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMDeviceMotion *motion, NSError *error){.....} } 在后台线程上,如下所示: [currentMotionHandler performSelec

我正在执行以下方法:

MotionHandler.m

-(void)startAccelerationUpdates
{
    [motionManagerstartDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]withHandler:^(CMDeviceMotion *motion, NSError *error){.....}
}
在后台线程上,如下所示:

[currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];
但是上面的方法使用
主队列
(在主线程上)执行必要的更新,即使我在后台线程上调用它。。那么,加速更新是在后台线程上执行还是在主线程上执行,我很困惑

更有趣的是,当我再次在后台线程上调用上述方法时,但这次使用
当前队列
,我没有得到任何更新。有人能解释一下在以下设备上运行的区别吗:

 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

在当前的实施中?谢谢大家!

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

currentQueue的用途是,运行的操作可以确定它们所在的队列,因此它们可以潜在地对该队列上的新操作进行排队

  • 一个后台线程,但在主队列上
  • 不可能-NSO操作的主队列始终与主线程关联

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

  • 主线程,但在主队列上
  • 见1)

  • 主线程,但在当前队列上
  • 如果您将一个操作排队到mainQueue(我们知道它总是在mainThread上),并且您请求currentQueue,它将返回mainQueue:

    [NSOperationQueue currentQueue] == [NSOperationQueue mainQueue];
    

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

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

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

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

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

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

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

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

    不幸的是,你的声明

    更有趣的是,当我在 再次使用后台线程,但这次使用当前队列,我得到 没有更新

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

    我将键入您对当前队列的使用情况

    我假定您的意思是将
    [NSOperationQueue mainQueue]
    替换为
    [NSOperationQueue currentQueue]

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

    currentQueue

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

    +
    (id)当前队列

    返回值

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

    讨论

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

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

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


    祝你好运

    谢谢你们的回答,非常有启发性