#concurrency #ios4 #nsurlconnection #nsoperation #nsrunloop
#параллелизм #ios4 #nsurlconnection #nsoperation #nsrunloop
Вопрос:
Я пытаюсь запустить NSURLConnection async во вторичном потоке (целевой является iOS4), для этого я создал параллельную NSOperation, я думаю, что я почти у цели, но не совсем понимаю следующее:
1) в iOS4 NSOperationQueue addOperation запускает операцию в новом потоке из-за использования GCD, основываясь на технических вопросах и ответах QA1712, однако мои тесты (симулятор и iPad) показывают, что start () всегда вызывается в главном потоке, есть идеи, нужна ли мне проверка здесь: если в главном потоке, то создать новый?
2) если бы start действительно был вызван во вторичном потоке с помощью addOperation (), тогда я мог бы запустить свое асинхронное NSURLConnection, запланировав текущий NSRunLoop:
[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.connection start];
как в примере LinkedImageFetcher здесь, и мне не нужно было бы выполнять цикл до завершения с:
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);
3) предполагая, что моя пользовательская функция NSOperation start () вызывается в основном потоке и 2) верна, и я создаю новый поток в start () для вызова моего пользовательского метода main () с:
[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
Затем в моем main () мне нужно запустить цикл выполнения текущего потока:
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!isCompelted);
Это единственный экземпляр, в котором мне удалось запустить NSURLConnection в параллельной NSOperation, но я не уверен, что мне действительно нужно запускать RunLoop, если поток был предоставлен GCD, как указано в технических примечаниях, могу ли я следовать логике в 2) или мне все равно придется запускать runloop потока? Как я могу протестировать поток, предоставляемый GCD?
Большое спасибо за любые разъяснения
Комментарии:
1. используйте простой метод подключения (как предложил @vaubry — Асинхронное NSURLConnection), а затем используйте NSOperationQueue для синтаксического анализа. Это поможет вам в достижении того, чего вы хотите.
Ответ №1:
Ну, я в конце концов разобрался с этим, поэтому подумал, что людям могут быть интересны детали:
1) start () был вызван в основном потоке, потому что я использовал [NSOperationQueue mainQueue] вместо создания новой очереди с помощью [[NSOperationQueue allc] init]. Однако проверка в NSOperation start() того, был ли текущий поток MainThread или нет, а затем вызов main () непосредственно оттуда или путем создания нового потока (в случае, если мы были в MainThread) не повредила.
2) Я понял, что LinkedImageFetcher слишком сложен для понимания циклов выполнения и потоков, и в этом нет необходимости, потому что тема не такая сложная. Все, что требуется в методе start(), — это поддерживать цикл выполнения вторичного потока до тех пор, пока мы не закончим (IsCompleted), все, что цикл выполнения для NSURLConnection выполняет прослушивание входных данных из соединения и запуск обратных вызовов (didreceivereponse, didreceivedata и т.д.).
3) да, запуск цикла выполнения необходим для получения обратных вызовов соединения в том же (вторичном в данном случае) потоке.
Для получения дополнительной информации смотрите Циклы выполнения в Руководстве по программированию потоков.
Комментарии:
1. Просто подумал, что я оставлю комментарий и скажу огромное спасибо! Я хотел реализовать несколько загрузок, используя NSOperation и NSOperationQueue, просто потому, что я могу отменить и ограничить количество одновременных загрузок вместо внедрения моего собственного менеджера очередей. Ваш вопрос и ваш ответ, в сотрудничестве с блогом Дейва Дрибина ( dribin.org/dave/blog/archives/2009/05/05/concurrent_operations ) помогло мне разобраться в концепции использования фоновых потоков с асинхронными вызовами. У меня все еще есть некоторые сомнения, но я задам их после повторного просмотра документов !:) Еще раз спасибо!
Ответ №2:
Я не уверен, что понимаю, чего вы пытаетесь достичь: API NSURLConnection имеет встроенный асинхронный метод initWithRequest:delegate:
Есть ли какая-то конкретная причина, по которой вы не можете это использовать?
Комментарии:
1. Более простой дизайн и масштабируемость, я бы тоже хотел проанализировать ответ в bg, и мне нужно выполнить более одного запроса одновременно. Спасибо
2. Использование NSOperationQueue позволяет добавлять экземпляры NSOperation, которые загружают данные. В очереди вы можете установить максимальное количество операций для одновременного выполнения. Вы можете счесть 2 или 4 оптимальными для производительности. С GCD вам пришлось бы управлять максимумом самостоятельно, плюс NSOperation легко отменить.