Использование оператора 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 для ожидания изменения логической переменной не является правильным подходом для решения проблемы. Вот несколько проблем с этим методом
Ваш процессор не обязательно обременен проверкой переменной регулярно.
Это наглядно покажет, что разработчик не очень хорошо владеет базовыми навыками кодирования и возможностями, доступными на языке.
Если по какой-либо причине ваша переменная никогда не изменится, то ваш ЦП никогда не прекратит проверять значение bool в цикле while и блокирует выполнение дополнительного кода в том же потоке.
Вот несколько правильных подходов:
Блоки или замыкания: используйте блоки для асинхронного выполнения кода после завершения RenewAuthToken.
Делегаты: если блоки труднее понять, используйте делегатов и запускайте делегат, когда вы закончите с RenewAuthToken.
Уведомления: Добавьте наблюдателя для уведомлений в классах, который должен отвечать, когда RenewAuthToken сделан, и выбросить уведомление из асинхронной задачи и позволить классу перехватить его, выполнить код.
Блокировки: Если необходимо заблокировать выполнение потока до получения ответа, используйте блокировки для управления выполнением потока, а не используя цикл 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).