2013-03-18 2 views
0

EDIT: Сегодня я немного работал с моим кодом и дал фоновой задаче несколько преимуществ по сравнению с основной задачей потока. По сути, один поток работает с четными номерами в массиве, а другой работает с нечетными числами. Я дал фоновому потоку четное число, равное или меньшее, чем нечетная половина. Кроме того, я переместил while(!collisionDone) немного позже в код, насколько я могу сохранить его в потоковом режиме. Я положил NSLog туда, чтобы определить, является ли условие когда-либо ложным, когда оно достигает этой точки, и оно не срабатывало один раз. Кроме того, теперь сборка инструментов прекрасна. Это означает, что проблема заключается в остановке основного потока с циклом while. Так что теперь мой вопрос:Инструменты блоки Background Thread?

Как мне остановить главный поток, чтобы ждать, пока фоновый поток выполнит задачу? Возможно, продемонстрируйте, как один использует 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:, и, похоже, он запускает ровно еще один кадр!?!?!?

Мне нравятся идеи относительно того, почему именно это происходит и как это исправить. Я сомневаюсь, что он не связан с многопоточным процессом, так как все в одном потоке исправляет его.

+0

вы можете присоединиться к вашей теме, вместо того, чтобы делать активное ожидание, проверьте [этот ответ из] (HTTP: // StackOverflow .com/questions/3614780/how-to-join-threads-in-object-c-without-use-delegates-callback), вероятно, не исправить вашу проблему, но лучше всего подходит для потоковой передачи – Fonix

+0

Спасибо за совет, но я не совсем уверен, как я должен использовать NSLock или любой из его подклассов, чтобы основной поток ожидал завершения фонового потока. Я понимаю, что цикл while - это не самый эффективный способ ожидания. В любом случае, начиная с последнего изменения моего кода, условие будет ложным только тогда, когда оно попадает в цикл while в редких случаях (см. Мое редактирование). – WolfLink

+0

использовать большой метод отправки в этом ответе, гораздо проще реализовать/понять. – Fonix

ответ

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

Да, это связано с многопоточным и вашим опросом на основной теме. Вместо этого вы должны поместить обратный вызов в фоновый поток. И не блокирует основной поток.

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

делают вместо

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

Edit: (! CollisionDone)

в то время как

всегда верно, потому что, когда вы создаете другой поток, инструкция застрял в " while "и не пересматривает каждый раз" collisionDone "так, как вы ожидали, но оценивайте его внутри области while.Кстати, может быть какой-то материал оптимизатора, и «collisionDone» можно было бы оценивать только в локальной области (но здесь я только предполагаю, поскольку он зависит от компилятора). Вы должны повторно ввести метод, чтобы заставить его работать или присоединиться к потоку, когда вы закончите. Поскольку вам не нужен сложный код для такого рода вещей, блок именно то, что вы хотите. libDispatch идеально подходят для этого.

Итак, вы можете попробовать «self.collisionDone», чтобы попытаться получить подлинный указатель. Но есть много шансов, что ничего не изменит.

Или вы можете делать свои вещи в фоновом режиме, и когда вы закончите, отправьте сигнал/обратный вызов вашему коду клиента. Вам не нужно делать опрос, как вы. Это действительно плохой дизайн (на самом деле мне доверяют;))

+0

Мне нужно подождать, пока и функция основного потока, и фон функция потока завершена до продолжения. Кроме того, после этой точки функции есть много вещей, и большая часть из них предполагает переупорядочение вида, поэтому это должно быть сделано на основном потоке. – WolfLink

+0

Wolf, я отредактировал свой ответ –

+0

Мне нужен один из потоков, чтобы ждать; Я должен убедиться, что оба потока завершили обработку, прежде чем продолжить. Я рассмотрел использование performSelectorOnMainThread :, но тогда я не могу быть уверен, что обработка основного потока завершена. – WolfLink

0

Непонятно, какой лучший подход к решению этой проблемы или какова фактическая причина проблемы (да, это while(!collisionDone) цикл, но почему?), Но ни одна из предложенных альтернатив не может выполнить эту работу должным образом. Хотя были предложены другие варианты, NSThread и performSelectorInBackground: были единственными способами, по которым я обнаружил функциональность, которую я ищу. Кроме того, после тестирования с отключенной частью многопоточности я понял, что у iPhone 4s намного лучший процессор, чем у iPhone 4, и я могу запустить игру на 60 FPS на iPhone 4 и новее без многопоточности (iPhone 4 может обрабатывать только 30 FPS). Наконец, я решил использовать многопоточность для использования двухъядерного процессора iPhone 4, поэтому половина столкновения будет выполнена в одном ядре, в то время как другое ядро ​​выполняет вторую половину. Я не уверен, что это происходит на самом деле, и я понятия не имею, как это обнаружить.

Мое заключение: полностью удалите эту попытку многопоточности из приложения. Это не нужно, и выгоды сомнительны.

@Fonix: Вопрос, который вы связали, показывает, что именно я пытаюсь сделать, однако ни одно из представленных решений не работает.