Я пишу код для рендеринга и поворота изображения, детали которого одновременно вычисляются и обновляются. Он работает без ошибок в одном потоке (со ссылкой на отображение), но выглядит неуклюже, и я не хочу, чтобы вычисления запускались по ссылке на отображение. Итак, я хочу выполнить весь код, связанный с OpenGL, в основном потоке (со ссылкой на отображение) и все вычисления во втором потоке (выполнение цикла while (YES)).
Я реализовал это с помощью NSThread. Некоторое время он прекрасно работает, а затем выходит из строя с «Поток 1: программа получила сигнал: «EXC_BAD_ACCESS»» во время glDrawArrays, а иногда появляются странные вспышки графики. Это то, что я ожидал, если основной поток считывает данные уровня модели в то же время, когда второй поток перезаписывает их.
Затем я определил NSLock в объекте модели и заблокировал его для всей записи (в моем классе модели) и чтения (в моем классе представления)... но это все равно может привести к той же ошибке, и графика все еще время от времени имеет странные вспышки .
Я сделал что-то не так здесь, или моя проблема где-то еще?
Во-вторых, как правильно остановить второй поток в этом случае? Ссылка на класс NSThread предлагает использовать отмену, проверку isCancelled и выход, если это так, но также говорит, что следует избегать вызова выхода.
Вот модификации кода - в моем классе контроллера (я использую XCode 4.2 с ARC, все мои ивары неатомарны):
@interface MyController : NSObject {
NSThread *calcThread;
...
}
// (I do not give it an @property or @synthesize line)
@implementation MyController
- (void) awakeFromNib {
calcThread = [[NSThread alloc] initWithTarget:self
selector:@selector(calcLoop:) object:nil];
[calcThread start];
...
}
- (void) calcLoop:(id)arg {
@autoreleasepool {
while (YES)
[myModel calculate];
}
}
...
Я поместил NSLock в свой класс модели:
@interface MyModel : NSObject {
NSLock* oLock;
...
}
@property (nonatomic, strong) NSLock* oLock;
@implementation myModel
-(id) init {
oLock = [[NSLock alloc] init];
...
}
-(void) changeModelAppearance {
[oLock lock];
...
[oLock unlock];
}
...
и в моем классе просмотра:
@implementation MyView
-(void) modelUpdated:(NSNotification *) notification {
// modelUpdated is called via the NSNotificationCenter
MyModel* myModel = (MyModel*) [notification object];
[myModel.oLock lock];
... // update OpenGL structures with data from myModel
[myModel.oLock unlock];
}
...
Спасибо!
glDrawArrays
? - person 一二三   schedule 27.12.2011glDrawArrays
находится в классе представления, в другом методе (render
); это вообще не относится к модели. - person Racing Tadpole   schedule 28.12.2011modelUpdated
может обновлять структуры OpenGL одновременно с вызовом методаrender
, поскольку NSNotificationCentre может вызывать его из любого потока. Так что теперь я вставил вторую блокировку в modelUpdated, а также поместил ее в метод рендеринга вокругglDrawArrays
. Но я все еще получаю ту же ошибку. - person Racing Tadpole   schedule 02.01.2012modelUpdated:
, изменяются/освобождаются до вызоваrender
? - person 一二三   schedule 02.01.2012NSLock
, когда другие ivars в любом классе модели читаются или записываются. (Я используюNSLock
, если добавляется изменяемый массив.) - person Racing Tadpole   schedule 02.01.2012modelUpdated:
- фактически всю структуруNSNotification
, которую я построил, - и теперь проверьте в верхней частиrender
, было ли обновление. Если есть, то делаю то, что раньше было вmodelUpdated:
. Это означает, что мой класс представления теперь имеет ссылку на объект модели, чего я пытался избежать. Но это означает, что я могу избавиться от двух взаимосвязанныхNSLock
, и все заработает. Так что спасибо! - person Racing Tadpole   schedule 22.01.2012