代码之家  ›  专栏  ›  技术社区  ›  WolfLink

仪器阻塞背景线程?

  •  0
  • WolfLink  · 技术社区  · 11 年前

    编辑: 今天,我对代码进行了一些处理,并使后台线程任务比主线程任务具有一些优势。本质上,一个线程处理数组中的偶数项,而另一个线程则处理奇数项。我给了背景线程偶数的一半,它要么等于奇数的一半,要么比奇数的一半少一。此外,我移动了 while(!collisionDone) 到代码的后面一点,尽我所能保持线程安全。我放了一个 NSLog 在那里检测当条件达到该点时是否为假,并且它没有触发过一次。此外,现在建造的仪器运行良好。这意味着问题是使用while循环来拖延主线程。这意味着我现在的问题是:

    我应该如何暂停主线程以等待后台线程完成任务?也许可以演示如何使用 NSLock 以实现该功能?

    今天我添加了多线程,试图减少游戏中的延迟。我正在使用NSTimer调用我的时间循环函数,如下所示:

    [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(time:) userInfo: nil repeats: true];
    

    然后,在该函数中,我有:

    //run collision using multithreading
        collisionDone = false;
        [self performSelectorInBackground:@selector(collideBackground:) withObject:objectToSend];
        [self collideMain:objectToSend];
        while (!collisionDone) {
            //notdone
        }
    

    这个想法是,我在一个线程上运行一组碰撞检查,在另一个线程中运行另一组。空while循环是为了确保后台线程在继续执行函数之前已经完成。在这个位之后,代码继续更新视图。

    这一切正常运行,但当我去仪器公司检查我的FPS时,我发现游戏冻结了,似乎在时间循环的第一次运行中冻结了。在多线程之前,该应用程序在Instruments中运行良好,除了简单地使用 [self collideBackground:objectToSend] 而不是将其发送到另一个线程。后台线程似乎没有完成或根本没有运行,因此collisionDone将始终为false,因此应用程序将在无休止的循环中等待,直到我杀死它。

    此外,我试着用 [self collideBackground:arrayToSend]; ,然后它又开始工作了。我试过的另一件事是 NSLog(@"called"); 在一开始 viewWillAppear: 它似乎又多跑了一帧!?!?!?

    我想知道为什么会发生这种情况,以及如何修复它。我怀疑这与多线程无关,因为在一个线程上做所有事情都可以修复它。

    3 回复  |  直到 11 年前
        1
  •  0
  •   Mr Bonjour    11 年前

    是的,它与多线程以及您在主线程上的轮询有关。您应该在后台线程中放入一个回调。并且不会阻塞主线程。

    // is not good at all
    collisionDone = false;
    /*  etc... that will make collision to true */
     while (!collisionDone) {
        }
    

    改为make

      [self computeSomethingOnBagroundWhithData: nil onCompletion:^{
        // callBack stuff
    }]
    

    编辑:

    while(!碰撞完成)

    始终为true,因为当您创建另一个线程时,指令被困在“while”语句中,并且不会像您预期的那样每次“collisionDone”都重新评估,而是在while范围内对其进行评估。顺便说一句,可能有一些优化器的东西,并且“collisionDone”只能在本地范围内进行评估(但这里我只是猜测,因为它依赖于编译器)。您应该重新输入该方法以使其工作,或者在完成后加入线程。由于您不希望这类东西使用复杂的代码,所以块正是您想要的。libDispatch非常适合这一点。

    因此,您可以尝试“self.collisionDone”以尝试获得真正的指针。但有很多机会不会改变任何事情。

    或者,您可以在后台完成您的工作,完成后,向您的客户端代码发送信号/回调。你不需要像以前那样进行投票。这真是糟糕的设计(真的相信我;)

        2
  •  0
  •   WolfLink    11 年前

    目前尚不清楚解决这个问题的最佳方法是什么,也不清楚问题的实际原因是什么(是的 while(!collisionDone) 循环,但为什么?),但所提出的替代方案中没有一个能够正确地完成这项工作。尽管已经提出了其他选项,但NSThread和performSelectInBackground:是我检测到我正在寻找的功能的唯一方法。此外,在关闭多线程部分进行测试后,我意识到iPhone 4s的处理器比iPhone 4好得多,而且我可以在iPhone 4s和更新版本上以60 FPS的速度运行游戏,而无需多线程(iPhone 4只能处理30 FPS)。最后,我打算让我的多线程使用iPhone 4s的双核处理器,这样一半的冲突将在一个内核中完成,而另一个内核则在另一半中完成。我不确定这是否真的发生了,我也不知道如何检测到这一点。

    我的结论是:从应用程序中完全删除这种多线程的尝试。这是不必要的,而且好处也令人怀疑。

    @Fonix:你提到的问题正好表明了我想做什么,然而,他们提出的解决方案似乎都不起作用。

        3
  •  0
  •   WolfLink    11 年前

    在学校与我的程序员朋友讨论后的最终解决方案是:

    //threadLock is an NSLock declared in the .h
    -(void)timeLoop {
         [self performSelectorInBackground:@selector(collideBackground) withObject:nil];
         [self collideMainAtStartingPoint:0];
    
         [threadLock lock];
         [threadLock unlock];
    
         //update the view hierarchy and stuff like that
    }
    -(void)collideBack {
         [threadLock lock];
         [self collideMainAtStartingPoint:2];
         [threadLock unlock];
    }