Цель C: блокировка потока до завершения NSTimer (iOS) - PullRequest
0 голосов
/ 25 апреля 2011

Я искал и пытался запрограммировать для себя ответ на этот вопрос.

В моем контроллере mainView работает вторичный поток, который затем запускает таймер, который ведет обратный отсчет до 0.

Пока этот таймер работает, вторичный поток, который инициировал таймер, должен быть приостановлен / заблокирован.

Когда таймер достигнет 0, вторичный поток должен продолжиться.

Ive Экспериментировал с обоимиNSCondition и NSConditionLock безрезультатны, так что идеально подходите к решениям, которые решают мою проблему с кодом, или указывают на руководство о том, как решить эту проблему.Не те, которые просто заявляют «Используй Х».

- (void)bettingInit {    
    bettingThread = [[NSThread alloc] initWithTarget:self selector:@selector(betting) object:nil];
    [bettingThread start];
}

- (void)betting {

    NSLog(@"betting Started");
    for (int x = 0; x < [dealerNormalise count]; x++){
        NSNumber *currSeat = [dealerNormalise objectAtIndex:x];
        int currSeatint = [currSeat intValue];
        NSString *currPlayerAction = [self getSeatInfo:currSeatint objectName:@"PlayerAction"];
        if (currPlayerAction != @"FOLD"){
            if (currPlayerAction == @"NULL"){                
                [inactivitySeconds removeAllObjects];
                NSNumber *inactivitySecondsNumber = [NSNumber numberWithInt:10];
                runLoop = [NSRunLoop currentRunLoop];
                betLooper = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(betLoop) userInfo:nil repeats:YES];
                [runLoop addTimer:[betLooper retain] forMode:NSDefaultRunLoopMode];
                [runLoop run];

                // This Thread needs to pause here, and wait for some input from the other thread, then continue on through the for loop

                NSLog(@"Test");

            }
        }
    }
}

- (void)threadKiller {
    [betLooper invalidate];

    //The input telling the thread to continue can alternatively come from here
    return;


}

- (void)betLoop {
    NSLog(@"BetLoop Started");
    NSNumber *currentSeconds = [inactivitySeconds objectAtIndex:0];
    int currentSecondsint = [currentSeconds intValue];
    int newSecondsint = currentSecondsint - 1;
    NSNumber *newSeconds = [NSNumber numberWithInt:newSecondsint];
    [inactivitySeconds replaceObjectAtIndex:0 withObject:newSeconds];
    inacTimer.text = [NSString stringWithFormat:@"Time: %d",newSecondsint];                      

    if (newSecondsint == 0){

        [self performSelector:@selector(threadKiller) onThread:bettingThread  withObject:nil waitUntilDone:NO];

        // The input going to the thread to continue should ideally come from here, or within the threadKiller void above
    }
}

Ответы [ 2 ]

1 голос
/ 25 апреля 2011

Вы не можете запустить таймер в потоке и одновременно спать в потоке. Вы можете пересмотреть, нужна ли вам вообще нить.

Здесь есть несколько вещей, на которые нужно обратить внимание. Во-первых, когда вы планируете свой таймер:

betLooper = [NSTimer scheduledTimerWithTimeInterval:1 
                                             target:self 
                                           selector:@selector(betLoop:) 
                                           userInfo:nil 
                                            repeats:YES];

он добавляется и сохраняется текущим циклом выполнения этим методом , поэтому вам не нужно делать это вручную. Просто [myRunLoop run]. Аргумент селектора вашего таймера также недопустим - «целевой метод» таймера должен выглядеть следующим образом :

- (void)timerFireMethod:(NSTimer *)tim;

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

Во-вторых, неясно, что вы подразумеваете под "этим потоком нужно спать, чтобы ждать ввода". Когда вы планируете этот таймер, метод (betLoop) вызывается в том же потоке . Если бы вы спали в потоке, таймер тоже остановился бы.

Вы, кажется, немного запутались в отношении методов / потоков. Метод betting работает на вашей ветке. Он не является потоком, и можно вызывать другие методы из betting, которые также будут в этом потоке. Если вы хотите, чтобы метод дождался завершения другого метода, просто вызовите второй метод внутри первого:

- (void)doSomethingThenWaitForAnotherMethodBeforeDoingOtherStuff {
    // Do stuff...
    [self methodWhichINeedToWaitFor];
    // Continue...
}

Я думаю, вы просто хотите позволить betting вернуться; цикл выполнения поддержит выполнение потока, и, как я уже сказал, другие методы, которые вы вызываете из методов в потоке, также находятся в потоке. Затем, когда вы завершили обратный отсчет, вызовите другой метод, чтобы выполнить любую необходимую работу (вы также можете сделать недействительным таймер внутри betLoop:), и завершить поток:

- (void)takeCareOfBusiness {
  // Do the things you were going to do in `betting`
  // Make sure the run loop stops; invalidating the timer doesn't guarantee this
  CFRunLoopStop(CFRunLoopGetCurrent());    
  return;    // Thread ends now because it's not doing anything.
}

Наконец, поскольку метод таймера находится в том же потоке, вам не нужно использовать performSelector:onThread:...; просто вызовите метод как обычно.

Обратите внимание на Руководство по программированию потоков .

Также не забудьте освободить созданный вами объект bettingThread.

0 голосов
/ 25 апреля 2011

NSThread имеет метод класса + (void)sleepForTimeInterval:(NSTimeInterval)ti.Посмотрите на это:).

...