iOS-приложение зависает с NSConditionLock

У меня странная проблема с зависанием приложения в определенный момент. Я думаю, это связано с тем, как я использую NSConditionLock,

Theres библиотека, которую мне дали использовать, которая состоит из серии вопросов опроса, но она работает таким образом, что она переходит непосредственно к последнему вопросу, не принимая ответы, следовательно, необходимо приостановить поток и принять ввод от пользователь.

Я не использовал его раньше, так что, может быть, кто-то может помочь, если я неправильно его реализую? Пожалуйста, дайте мне знать, если предоставленного кода недостаточно.

- (void)viewDidLoad
{
    [super viewDidLoad];
//INITIALISE CONDITION LOCK WITH CONDITION 0
     condition=[[NSConditionLock alloc]initWithCondition: 0];
}


- (IBAction)startPressed:(UIButton*)sender {
if (sender.tag == 1) {
//START BACKGROUND THREAD
 surveyThread = [[NSThread alloc] initWithTarget:self selector:@selector(runProjecttest)      object:nil];
        [surveyThread start];
}
else
{
 //DO SOME STUFF AND THEN UNLOCK
 [condition unlockWithCondition:1];
}
}


- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[self performSelectorOnMainThread:@selector(showUI:) withObject:task waitUntilDone:YES];
 [condition lockWhenCondition: 1];
}

РЕДАКТИРОВАТЬ: Короче говоря, я хочу, чтобы Objc эквивалент этого фрагмента Java...

this.runOnUiThread(showUI);
    try 
    {
        //SLEEP         
        Thread.sleep(1000*60*60*24*365*10);
    } 
    catch (InterruptedException e) 
    {
                   //WAKE
        setResponse(at,showUI);
    }

РЕДАКТИРОВАТЬ 2: метод ShowUI по запросу Пола.

 [self removePreviousSubViews];

 switch ([task getType]) {
        case SingleChoiceType:
        {
            NSLog(@"SingleChoiceType");
            isMultipleChoice = NO;
            [self addSingleChoiceView:nil];
            break;
        }
        case TextType:
        {
            NSLog(@"TextType");
            self.txtTextType.keyboardType=UIKeyboardTypeDefault;
            [self addTextTypeView:nil];

            break;
        }
...more cases
}

-(void)addTextTypeView:(NSSet *)objects
{
    self.txtTextType.text = @"";
    CGRect frame = self.txtQuestionType.frame;
//    frame.size = [self.txtQuestionType sizeThatFits: CGSizeMake(self.txtQuestionType.frame.size.width, FLT_MAX)];
        frame.size.height = [self textViewHeightForAttributedText:self.txtQuestionType.text andWidth:self.txtQuestionType.frame.size.width andTextView:self.txtQuestionType];


    self.txtQuestionType.frame=frame;

    self.textTypeView.frame = CGRectMake((self.view.frame.size.width - self.textTypeView.frame.size.width)/2, ( self.txtQuestionType.frame.origin.y+self.txtQuestionType.frame.size.height), self.textTypeView.frame.size.width, self.textTypeView.frame.size.height);

    [self.view addSubview: self.textTypeView];
}

1 ответ

Я согласен с BryanChen, я думаю, у вас может быть другая проблема. Без подробностей о библиотеке опросов невозможно подтвердить, но если предположить, что это UIViewController, который принимает сенсорный ввод для прохождения ряда вопросов, трудно понять, почему это проблема с многопоточностью - она ​​просто не должна развиваться без взаимодействия с пользователем.

Что в сторону, ваше использование NSCondtionLock тоже не выглядит правильно.

По сути NSConditionLock имеет NSInteger, который представляет текущее "условие", но просто подумайте о нем числа. Затем вы можете выполнить две основные операции:

lockWhenCondition:x будет блокировать текущий поток, пока "условие" не станет "х" и блокировка не будет доступна. Затем он будет требовать блокировки.

unlockWithCondition:y снимает блокировку и устанавливает условие в 'y'

Есть также методы для установки таймаутов (lockBeforeDate) и попытаться получить блокировку без блокировки (tryLock, tryLockWhenCondition).

Для синхронизации двух потоков используется общая схема

  1. Инициализация Блокировка для условия "х"
  2. Тема 1 lockWhenCondition:x -Этот поток может требовать блокировки, потому что это х
  3. Тема 2 lockWhenCondition:y - Этот поток будет заблокирован, потому что блокировка х
  4. Тема 1 завершает работу, unlockWithCondition:y - Это позволит потоку 2 требовать блокировки и разблокировать этот поток

Ваш код выглядит странно, потому что вы запускаете поток в предложении if, но разблокируете в предложении else. Я бы подумал, что у вас будет что-то вроде -

-(IBAction)startPressed:(UIButton*)sender {
    if (sender.tag == 1) {
    //START BACKGROUND THREAD
     surveyThread = [[NSThread alloc] initWithTarget:self selector:@selector(runProjecttest)      object:nil];
        [surveyThread start];
        [condition:lockWithCondition:1];     //  This will block until survey thread completes
        [condition:unlockWithCondition:0];   //  Unlock and ready for next time
    }

}

- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[condition lockWhenCondition: 0];
[self performSelectorOnMainThread:@selector(showUI:) withObject:task waitUntilDone:YES];
[condition unlockWithCondition:1];
}

НО это выглядит как рецепт для взаимоблокировки, потому что вы выполняете селектор showUI в главном потоке, который заблокирован, ожидая завершения потока опроса.

Что возвращает нас к вопросу, что делает showUI делать и почему он пропускает прямо до конца?

Другие вопросы по тегам