仪器阻止背景线程?

时间:2013-03-18 07:41:33

标签: ios objective-c multithreading instruments

修改 今天我使用了我的代码,并给了后台线程任务一些优于主线程任务的优点。基本上一个线程正在使用数组中的偶数项,另一个正在处理奇数。我给后台线程的偶数一半,它将等于或小于奇数的一半。此外,我在代码中将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时,我发现游戏冻结了,似乎它在时间循环的第一次运行中某处冻结。在多线程之前,应用程序运行得很好,除了简单地使用[self collideBackground:objectToSend]而不是将其发送到另一个线程之外,它基本上都是相同的。看起来后台线程没有完成或根本没有运行,所以collisionDone总是假的,因此应用程序将在无限循环中等待直到我杀死它。

另外,我尝试用[self collideBackground:arrayToSend];替换该行,然后重新开始工作。我尝试的另一件事是NSLog(@"called");viewWillAppear:的最开始,它似乎再运行一帧!?!?!?

我想知道为什么会发生这种情况以及如何解决这个问题。我怀疑它与多线程无关,因为在单个线程上执行所有操作都会修复它。

3 个答案:

答案 0 :(得分:0)

是的,它与多线程和主线程上的轮询有关。您应该将回调放入后台线程中。而不是阻止主线程。

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

改为

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

修改

while(!collisionDone)

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

所以你可以试试“self.collisionDone”以试图获得真正的指针。但是有很多机会不会改变任何东西。

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

答案 1 :(得分:0)

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

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

@Fonix:您链接的问题显示了我正在尝试做的事情,但是,他们提供的解决方案似乎都没有起作用。

答案 2 :(得分:0)

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

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