Использование оператора while(true) для правильного подхода в программировании iOS?

В цели C я заставляю свою программу ждать, используя цикл while

doInitialize()
{
 dispach_group_t loadDataGroup=dispatch_group_create();
 dispatch_group_async(loadDataGroup,...get_global_queue(..),0),^{
   renewauth();
 }
 dispatch_group_notify(loadDataGroup,...get_global_queue(..),0),^{
   //Do other tasks once renew session has completed...
 }
}
renewauth()
{
 RenewAuthTokenInProgress=true;
 startRenewThread();
 **while (RenewAuthTokenInProgress);**
}

В свою очередь функция startRenewThread() также выполняет операцию dispatch_async внутри. Так что я должен подождать refreshAuth().

А асинхронная задача в startRenewThread обновит переменную bool после успешного обновления.

Есть ли лучший способ сделать это, кроме dispatch_groups? И хорошо ли заставлять другие потоки ждать с оператором while (true)?

3 ответа

Решение

Манодж Кумар,

использование цикла while для ожидания изменения логической переменной не является правильным подходом для решения проблемы. Вот несколько проблем с этим методом

  1. Ваш процессор не обязательно обременен проверкой переменной регулярно.

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

  3. Если по какой-либо причине ваша переменная никогда не изменится, то ваш ЦП никогда не прекратит проверять значение bool в цикле while и блокирует выполнение дополнительного кода в том же потоке.

Вот несколько правильных подходов:

  1. Блоки или замыкания: используйте блоки для асинхронного выполнения кода после завершения RenewAuthToken.

  2. Делегаты: если блоки труднее понять, используйте делегатов и запускайте делегат, когда вы закончите с RenewAuthToken.

  3. Уведомления: Добавьте наблюдателя для уведомлений в классах, который должен отвечать, когда RenewAuthToken сделан, и выбросить уведомление из асинхронной задачи и позволить классу перехватить его, выполнить код.

  4. Блокировки: Если необходимо заблокировать выполнение потока до получения ответа, используйте блокировки для управления выполнением потока, а не используя цикл while

РЕДАКТИРОВАТЬ

Как указано в комментариях fogmeister

Если вы заблокируете основной поток слишком долго с помощью цикла while(true), то приложение будет фактически остановлено сторожевым таймером iOS, так как оно будет считать, что оно аварийно завершилось.

Пожалуйста, взгляните на ссылку: понять причины прекращения работы сторожевого таймера iOS, предоставленные fogmeister

Надеюсь, поможет.

Я верю что тебе нужно это semaphore лайк:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

dispatch_semaphore_t sem = dispatch_semaphore_create(0);
__block BOOL done = FALSE;
while (true) {

    [self someCompletionMethod completion:^(BOOL success) {

        if(success) { // Stop condition
            done = TRUE;
        }
        // do something
        dispatch_semaphore_signal(sem); // This will let a new iteration
    }];

    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

    if(done) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // Dispatch to main
            NSLog(@"Done!");
            break;
        });
    }
}

});

Семафоры - это многопоточное понятие старой школы, представленное миру очень скромным Эдсгером В. Дейкстрой. Семафоры - сложная тема, потому что они основаны на тонкостях функций операционной системы.

Вы можете посмотреть учебное пособие по семафору и ознакомиться с другими ссылками: https://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2

Я надеюсь это тебе поможет.

То, что вы делаете, абсолютно смертельно. Он блокирует работающий поток (предположительно основной поток), поэтому пользовательский интерфейс заморожен. Он работает на одном ядре при 100% нагрузке без какой-либо причины, которая быстро разряжает батарею и нагревает телефон. Это принесет вам очень, очень несчастных клиентов или очень, очень счастливых бывших клиентов.

Все что угодно должно выполняться в фоновом режиме: startRenewThread должен запускать какое-то действие, которое устанавливает RenewAuthTokenInProgress = NO и устанавливает, есть ли новый токен, или нет, а затем запускает дальнейшее действие.

Это абсолютно необходимый шаблон программирования на iOS (и, насколько я знаю, на Android).

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