0

В моем приложении у меня есть три интернет-операции, которые запускаются сразу. Они не зависят друг от друга, поэтому я запускаю каждый из них в фоновом потоке. Каждый из них должен быть завершен, хотя до того, как мое приложение сможет перейти к обработчику завершения.Приложение iOS ведет себя по-разному с помощью схемы отладки vs

Метод, который запускает каждый из трех, принимает в качестве параметра блок-код, который выполняет функции обработчика завершения. Этот метод также имеет локальную переменную, называемую internetOperationsRemaining, которую я установил равной 3, прежде чем я начну каждую из трех интернет-операций.

Когда каждый из интернет-операций завершен, я уменьшаю количество интернет-операций. На основном потоке. Это приводит к тому, что internetOperationsRemaining == 0, когда все они завершены.

Чтобы прослушать это условие, я запускаю жесткий цикл в другом фоновом потоке, который просто зацикливает на себя, ожидая, пока internetOperationsRemaining равняется 0. Как только это произойдет, я вызываю обработчик завершения, который был передан как параметр, как описано выше.

//Spawn a background thread and loop in it until 
    //allInternetOperationComplete == true. 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     while(internetOperationsRemaining > 0) 
     { 
      //Just spins in here on a background thread waiting 
      //on the internet to finish. 
     } 

     //Now that internetOperationsRemaining == 0, kill the NSURL session 
     //and call the completion handler on the main thread. 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      [session finishTasksAndInvalidate]; 
      completionHandler(); 
     }); 
    }); 

странное поведение, которое я вижу в том, что приложение работает отлично, если я отладка установлена ​​в схеме, и это не, если я выбран релиз. Он просто никогда не выходит из цикла while.

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

while(internetOperationsRemaining > 0) 
    { 
     //Just spins in here on a background thread waiting 
     //on the internet to finish. 
     int i=0; 
     ++i; 
    } 

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

ответ

1

Без запуска кода для проверки, я бы подумал, что то, что происходит, это какая-то оптимизация компилятора, которая встречается только в коде Release.

Я думаю, что настоящая проблема, хотя это больше о дизайне. Использование счетчиков и вращение нити невелики. Я бы предложил изучить использование NSOperations. Вы можете настроить иерархии операций, чтобы ваша операция завершения зависела от других трех. Прочитайте об использовании операций, параллельных очередей и зависимостей, и вы получите эту идею.

+0

Спасибо за ответ! Мне не понравилось, что круглая петля тоже вращалась, но не знал о NSOperation. Потребовалось около 5 минут чтения, чтобы понять, что это дает именно то, что я пытался сделать. Я буду переписывать этот раздел кода завтра, используя ваше предложение, и если он исправит проблему (я подозреваю, что это будет), я обязательно выберу ваш ответ в качестве ответа. Еще раз спасибо! – Scooter

+0

Метод вызывает то, что я жду, чтобы завершить каждый вызов методов NSURLSession, которые сами являются асинхронными с их собственными обработчиками завершения. Простое размещение этих методов в очереди NSOperations оставляет мне мою первоначальную проблему. Вызывается метод NSURLSession, завершается NSBlockOperation, и все это происходит до того, как методы NSURLSession завершены. Я просматриваю пользовательский подкласс NSOperation, чтобы увидеть, могу ли я заставить его работать таким образом. – Scooter

+0

Выяснилось, что это сложнее, чем я думал ... – Scooter